天天看點

linux 讀寫鎖

  1. 概述

    在某些場景下,讀資料操作比寫資料操作要頻繁,那麼可以使用讀寫鎖替代互斥鎖來提高應用程式的性能。

    讀寫鎖的通路規則如下:

  • 多個線程共享讀操作權限
  • 沒有讀或者寫操作時,才可以執行寫操作
  1. 主要操作
#include <pthread.h>
int pthread_rwclock_rdclock(pthread_rwlock_t *rwptr);//加讀出鎖,如果讀寫鎖被一個寫入者持有則堵塞
int pthread_rwclock_wrclock(pthread_rwlock_t *rwptr);//加寫入鎖,如果讀寫鎖被讀或者寫線程占有,則堵塞等待
int pthread_rwclock_unclock(pthread_rwlock_t *rwptr);//釋放鎖
// 非阻塞模式,如果不能馬上得到就傳回一個EBUSY錯誤
int pthread_rwclock_tryrdclock(pthread_rwlock_t *rwptr);
int pthread_rwclock_trywrclock(pthread_rwlock_t *rwptr);
           

讀寫鎖的初始化和銷毀

int pthread_rwclock_init(pthread_rwlock_t *rwptr, const pthread_rwlockattr_t *attr);
int pthread_rwclock_destory(pthread_rwlock_t *rwptr);
           

設定讀寫鎖屬性,屬性值為PTHREAD_PROCESS_PRIVATE或 PTHREAD_PROCESS_SHARED。前者表是讀寫鎖隻在本程序可用,後者表示可以多程序共享。

int pthread_rwclock_getpshared(const pthread_rwlockattr_t *attr, int *valptr);
int pthread_rwclock_setpshared(const pthread_rwlockattr_t *attr, int valptr);
           
  1. 舉例
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

long g_data = 0;
pthread_rwlock_t lock;  //讀寫鎖

void* wr_cb(void* arg) {
    while (1) {
        //加寫入鎖
        pthread_rwlock_wrlock(&lock);
        g_data++;
        usleep(10);
        printf("write clock, thread id: %lu, data: %d\n", pthread_self(),
               g_data);
        //釋放鎖
        pthread_rwlock_unlock(&lock);
        usleep(1000);
    }
    return NULL;
}

void* rd_cb(void* arg) {
    while (1) {
        //加讀出鎖
        pthread_rwlock_rdlock(&lock);
        printf("read clock, thread id: %lu, data: %d\n", pthread_self(),
               g_data);
        //釋放鎖
        pthread_rwlock_unlock(&lock);
        usleep(1000);
    }
    return NULL;
}

int main(int argc, char* argv[]) {
    pthread_t thd[4];  // 4個線程

    pthread_create(&thd[0], NULL, wr_cb, NULL);
    pthread_create(&thd[1], NULL, wr_cb, NULL);
    pthread_create(&thd[2], NULL, rd_cb, NULL);
    pthread_create(&thd[3], NULL, rd_cb, NULL);

    int i;
    for (i = 0; i < 4; i++) {
        pthread_join(thd[i], NULL);
    }

    //銷毀
    pthread_rwlock_destroy(&lock);
    return 0;
}
           
  1. 總結

    讀寫鎖的特性

  • 加讀出鎖: 來了N個線程做讀出操作,那麼都加鎖成功, 這叫讀鎖共享。如果先來了M個線程做讀出操作,後來了K個線程做寫入操作,又來了L個線程做讀操作。那麼從K個線程開始阻塞。後面即便L個線程是讀操作也不可,這裡順序的一緻性。
  • 加寫入鎖,當線程T加鎖成功時,其他任何線程都有阻塞,這樣寫鎖獨占
  • 線程R加讀鎖,線程W加寫鎖,如果同時到達,那麼寫鎖優先。

繼續閱讀