1. 程式人生 > >linux多執行緒之讀寫鎖

linux多執行緒之讀寫鎖

基本概念:

讀寫鎖也叫做共享互斥鎖。

當讀寫鎖是寫加鎖狀態時,在這個鎖被解鎖之前,所有試圖對這個鎖加鎖的執行緒都會被阻塞。當讀寫鎖在讀加鎖狀態,所有試圖以讀模式對它進行加鎖的執行緒都可以得到訪問權。

與互斥量相比,讀寫鎖在使用之前必須初始化,在釋放它們底層的記憶體之前必須銷燬。

一、鎖的初始化與銷燬

PTHREAD_RWLOCK_DESTROY(P)  POSIX Programmer's Manual PTHREAD_RWLOCK_DESTROY(P)

NAME
       pthread_rwlock_destroy,  pthread_rwlock_init - destroy and initialize a
       read-write lock object

SYNOPSIS
       #include <pthread.h>

       int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
       int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
              const pthread_rwlockattr_t *restrict attr);
兩個函式的返回值:若成功,返回0;否則,返回錯誤編號

二、讀鎖

PTHREAD_RWLOCK_RDLOCK(P)   POSIX Programmer's Manual  PTHREAD_RWLOCK_RDLOCK(P)

NAME
       pthread_rwlock_rdlock,  pthread_rwlock_tryrdlock  -  lock  a read-write
       lock object for reading

SYNOPSIS
       #include <pthread.h>

       int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
       int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
兩個函式的返回值:若成功,返回0;否則,返回錯誤編號
pthread_rwlock_tryrdlock函式可以獲取鎖時,返回0.否則,返回錯誤EBUSY

三、寫鎖

PTHREAD_RWLOCK_TRYWRLOCK(P)POSIX Programmer's ManuaPTHREAD_RWLOCK_TRYWRLOCK(P)

NAME
       pthread_rwlock_trywrlock,  pthread_rwlock_wrlock  -  lock  a read-write
       lock object for writing

SYNOPSIS
       #include <pthread.h>

       int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
       int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
兩個函式的返回值:若成功,返回0;否則,返回錯誤編號

pthread_rwlock_trywrlock函式可以獲取鎖時,返回0.否則,返回錯誤EBUSY

四、帶有超時的讀寫鎖

PTHREAD_RWLOCK_TIMEDWRLOCK(POSIX Programmer's ManPTHREAD_RWLOCK_TIMEDWRLOCK(P)

NAME
       pthread_rwlock_timedrdlock - lock a read-write lock for reading
       pthread_rwlock_timedwrlock - lock a read-write lock for writing

SYNOPSIS
       #include <pthread.h>
       #include <time.h>

       int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock,
              const struct timespec *restrict abs_timeout);
       int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock,
              const struct timespec *restrict abs_timeout);
兩個函式的返回值:若成功,返回0;否則,返回錯誤編號
如果它們不能獲取鎖,那麼超時到期時,這兩個函式將返回ETIMEDOUT

五、解鎖

PTHREAD_RWLOCK_UNLOCK(P)   POSIX Programmer's Manual  PTHREAD_RWLOCK_UNLOCK(P)

NAME
       pthread_rwlock_unlock - unlock a read-write lock object

SYNOPSIS
       #include <pthread.h>

       int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
返回值:若成功,返回0;否則,返回錯誤編號

讀寫鎖屬性:

讀寫鎖支援的唯一屬性是程序共享屬性。它與互斥量的程序共享屬性是相同的,這裡不展開討論。

例子:gcc pthread_rwlock.c -pthread

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

static int num = 0;
static int count = 100000;
static pthread_rwlock_t rwlock;

void Perror(const char *s)
{
    perror(s);
    exit(EXIT_FAILURE);
}

void* fun2(void *arg)
{
    pthread_t thread_id = pthread_self();
    printf("the thread2 id is %ld\n", (long)thread_id);
    int i = 1;
    for (; i<=count; ++i) {
        pthread_rwlock_wrlock(&rwlock);
        num += 1;
        pthread_rwlock_unlock(&rwlock);
    }
}

void* fun3(void *arg)
{
    pthread_t thread_id = pthread_self();
    printf("the thread3 id is %ld\n", (long)thread_id);
    int i = 1;
    for (; i<=count; ++i) {
        pthread_rwlock_wrlock(&rwlock);
        num += 1;
        pthread_rwlock_unlock(&rwlock);
    }
}

int main()
{
    int err;
    pthread_t thread1;
    pthread_t thread2;
    pthread_t thread3;

    // init
    pthread_rwlock_init(&rwlock, NULL);

    thread1 = pthread_self();
    printf("the thread1 id is %ld\n", (long)thread1);

    // Create thread
    err = pthread_create(&thread2, NULL, fun2, NULL);
    if (err != 0) {
        Perror("can't create thread2\n");
    }
    err = pthread_create(&thread3, NULL, fun3, NULL);
    if (err != 0) {
        Perror("can't create thread3\n");
    }

    // detach thread
    err = pthread_detach(thread2);
    if (err != 0) {
        Perror("can't detach thread2\n");
    }
    err = pthread_detach(thread3);
    if (err != 0) {
        Perror("can't detach thread3\n");
    }

    int i = 1;
    for (; i<=count; ++i) {
        pthread_rwlock_rdlock(&rwlock);
        int temp = num;
        pthread_rwlock_unlock(&rwlock);
    }

    sleep(10);
    printf("The num is %d\n", num);
    
    pthread_rwlock_destroy(&rwlock);
    return 0;
}


參考:《unix環境高階程式設計》·第三版

End;