一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

linux c 線程間同步(通信)的幾種方法

 lifei_szdz 2018-02-05

Linux下提供了多種方式來處理線程同步,最常用的是互斥鎖、條件變量、信號量和讀寫鎖。
下面是思維導(dǎo)圖:
這里寫圖片描述

一、互斥鎖(mutex)
  鎖機(jī)制是同一時(shí)刻只允許一個(gè)線程執(zhí)行一個(gè)關(guān)鍵部分的代碼。

1 . 初始化鎖

int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr);
  • 1

其中參數(shù) mutexattr 用于指定鎖的屬性(見下),如果為NULL則使用缺省屬性。
互斥鎖的屬性在創(chuàng)建鎖的時(shí)候指定,在LinuxThreads實(shí)現(xiàn)中僅有一個(gè)鎖類型屬性,不同的鎖類型在試圖對一個(gè)已經(jīng)被鎖定的互斥鎖加鎖時(shí)表現(xiàn)不同。當(dāng)前有四個(gè)值可供選擇:
(1)PTHREAD_MUTEX_TIMED_NP,這是缺省值,也就是普通鎖。當(dāng)一個(gè)線程加鎖以后,其余請求鎖的線程將形成一個(gè)等待隊(duì)列,并在解鎖后按優(yōu)先級獲得鎖。這種鎖策略保證了資源分配的公平性。
(2)PTHREAD_MUTEX_RECURSIVE_NP,嵌套鎖,允許同一個(gè)線程對同一個(gè)鎖成功獲得多次,并通過多次unlock解鎖。如果是不同線程請求,則在加鎖線程解鎖時(shí)重新競爭。
(3)PTHREAD_MUTEX_ERRORCHECK_NP,檢錯(cuò)鎖,如果同一個(gè)線程請求同一個(gè)鎖,則返回EDEADLK,否則與PTHREAD_MUTEX_TIMED_NP類型動作相同。這樣就保證當(dāng)不允許多次加鎖時(shí)不會出現(xiàn)最簡單情況下的死鎖。
(4)PTHREAD_MUTEX_ADAPTIVE_NP,適應(yīng)鎖,動作最簡單的鎖類型,僅等待解鎖后重新競爭。

2 . 阻塞加鎖

 int pthread_mutex_lock(pthread_mutex *mutex);
  • 1

3 . 非阻塞加鎖

  int pthread_mutex_trylock( pthread_mutex_t *mutex);
  • 1

該函數(shù)語義與 pthread_mutex_lock() 類似,不同的是在鎖已經(jīng)被占據(jù)時(shí)返回 EBUSY 而不是掛起等待。
4 . 解鎖(要求鎖是lock狀態(tài),并且由加鎖線程解鎖)

 int pthread_mutex_unlock(pthread_mutex *mutex);
  • 1

5 . 銷毀鎖(此時(shí)鎖必需unlock狀態(tài),否則返回EBUSY)

int pthread_mutex_destroy(pthread_mutex *mutex);
  • 1

  示例代碼:

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

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int gn;

void* thread(void *arg)
{
    printf("thread's ID is  %d\n",pthread_self());
    pthread_mutex_lock(&mutex);
    gn = 12;
    printf("Now gn = %d\n",gn);
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main()
{
    pthread_t id;
    printf("main thread's ID is %d\n",pthread_self());
    gn = 3;
    printf("In main func, gn = %d\n",gn);
    if (!pthread_create(&id, NULL, thread, NULL)) {
        printf("Create thread success!\n");
    } else {
        printf("Create thread failed!\n");
    }
    pthread_join(id, NULL);
    pthread_mutex_destroy(&mutex);
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

二、條件變量(cond)

  條件變量是利用線程間共享全局變量進(jìn)行同步的一種機(jī)制。條件變量上的基本操作有:觸發(fā)條件(當(dāng)條件變?yōu)?true 時(shí));等待條件,掛起線程直到其他線程觸發(fā)條件。

1 . 初始化條件變量 

   int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);
  • 1
 盡管POSIX標(biāo)準(zhǔn)中為條件變量定義了屬性,但在Linux中沒有實(shí)現(xiàn),因此cond_attr值通常為NULL,且被忽略。

2 . 有兩個(gè)等待函數(shù)
(1)無條件等待

      int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
  • 1
  (2)計(jì)時(shí)等待
      int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);
  • 1
  如果在給定時(shí)刻前條件沒有滿足,則返回ETIMEOUT,結(jié)束等待,其中abstime以與time()系統(tǒng)調(diào)用相同意義的絕對時(shí)間形式出現(xiàn),0表示格林尼治時(shí)間1970年1月1日0時(shí)0分0秒。

 
無論哪種等待方式,都必須和一個(gè)互斥鎖配合,以防止多個(gè)線程同時(shí)請求(用 pthread_cond_wait() 或 pthread_cond_timedwait() 請求)競爭條件(Race Condition)。mutex互斥鎖必須是普通鎖(PTHREAD_MUTEX_TIMED_NP)或者適應(yīng)鎖(PTHREAD_MUTEX_ADAPTIVE_NP),且在調(diào)用pthread_cond_wait()前必須由本線程加鎖(pthread_mutex_lock()),而在更新條件等待隊(duì)列以前,mutex保持鎖定狀態(tài),并在線程掛起進(jìn)入等待前解鎖。在條件滿足從而離開pthread_cond_wait()之前,mutex將被重新加鎖,以與進(jìn)入pthread_cond_wait()前的加鎖動作對應(yīng)。

3 . 激發(fā)條件
(1)激活一個(gè)等待該條件的線程(存在多個(gè)等待線程時(shí)按入隊(duì)順序激活其中一個(gè))  

      int pthread_cond_signal(pthread_cond_t *cond);
  • 1

(2)激活所有等待線程

  int pthread_cond_broadcast(pthread_cond_t *cond);
  • 1

4 . 銷毀條件變量

   int pthread_cond_destroy(pthread_cond_t *cond);
  • 1
  只有在沒有線程在該條件變量上等待的時(shí)候才能銷毀這個(gè)條件變量,否則返回EBUSY

說明:

  1. pthread_cond_wait 自動解鎖互斥量(如同執(zhí)行了pthread_unlock_mutex),并等待條件變量觸發(fā)。這時(shí)線程掛起,不占用CPU時(shí)間,直到條件變量被觸發(fā)(變量為ture)。在調(diào)用 pthread_cond_wait之前,應(yīng)用程序必須加鎖互斥量。pthread_cond_wait函數(shù)返回前,自動重新對互斥量加鎖(如同執(zhí)行了pthread_lock_mutex)。

  2. 互斥量的解鎖和在條件變量上掛起都是自動進(jìn)行的。因此,在條件變量被觸發(fā)前,如果所有的線程都要對互斥量加鎖,這種機(jī)制可保證在線程加鎖互斥量和進(jìn)入等待條件變量期間,條件變量不被觸發(fā)。條件變量要和互斥量相聯(lián)結(jié),以避免出現(xiàn)條件競爭——個(gè)線程預(yù)備等待一個(gè)條件變量,當(dāng)它在真正進(jìn)入等待之前,另一個(gè)線程恰好觸發(fā)了該條件(條件滿足信號有可能在測試條件和調(diào)用pthread_cond_wait函數(shù)(block)之間被發(fā)出,從而造成無限制的等待)。

  3. 條件變量函數(shù)不是異步信號安全的,不應(yīng)當(dāng)在信號處理程序中進(jìn)行調(diào)用。特別要注意,如果在信號處理程序中調(diào)用 pthread_cond_signal 或 pthread_cond_boardcast 函數(shù),可能導(dǎo)致調(diào)用線程死鎖

示例代碼1:

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

pthread_mutex_t mutex;
pthread_cond_t cond;

void hander(void *arg)
{
    free(arg);
    (void)pthread_mutex_unlock(&mutex);
}

void *thread1(void *arg)
{
    pthread_cleanup_push(hander, &mutex);
    while (1) {
        printf("thread1 is running\n");
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond,&mutex);
        printf("thread1 applied the condition\n");
        pthread_mutex_unlock(&mutex);
        sleep(4);
    }
    pthread_cleanup_pop(0);
}

void *thread2(void *arg)
{
    while (1) {
        printf("thread2 is running\n");
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond,&mutex);
        printf("thread2 applied the condition\n");
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
}

int main()
{
    pthread_t thid1,thid2;
    printf("condition variable study!\n");
    pthread_mutex_init(&mutex,NULL);
    pthread_cond_init(&cond,NULL);
    pthread_create(&thid1,NULL,thread1,NULL);
    pthread_create(&thid2,NULL,thread2,NULL);

    sleep(1);
    do {
        pthread_cond_signal(&cond);
    } while(1);

    sleep(20);
    pthread_exit(0);
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

示例代碼2:

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

static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

struct node
{
    int n_number;
    struct node *n_next;
}*head = NULL;

static void cleanup_handler(void *arg)
{
    printf("Cleanup handler of second thread.\n");
    free(arg);
    (void)pthread_mutex_unlock(&mtx);
}

static void *thread_func(void *arg)
{
    struct node *p = NULL;
    pthread_cleanup_push(cleanup_handler, p);

    while (1) {
        // 這個(gè)mutex主要是用來保證pthread_cond_wait的并發(fā)性。
        pthread_mutex_lock(&mtx);
        while (head == NULL) {
            /* 這個(gè)while要特別說明一下,單個(gè)pthread_cond_wait功能很完善,為何
            * 這里要有一個(gè)while (head == NULL)呢?因?yàn)閜thread_cond_wait里的線
            * 程可能會被意外喚醒,如果這個(gè)時(shí)候head != NULL,則不是我們想要的情況。
            * 這個(gè)時(shí)候,應(yīng)該讓線程繼續(xù)進(jìn)入pthread_cond_wait
            * pthread_cond_wait會先解除之前的pthread_mutex_lock鎖定的mtx,
            * 然后阻塞在等待對列里休眠,直到再次被喚醒(大多數(shù)情況下是等待的條件成立
            * 而被喚醒,喚醒后,該進(jìn)程會先鎖定先pthread_mutex_lock(&mtx);,再讀取資源
            * 用這個(gè)流程是比較清楚的。*/

            pthread_cond_wait(&cond, &mtx);
            p = head;
            head = head->n_next;
            printf("Got %d from front of queue\n", p->n_number);
            free(p);
        }
        pthread_mutex_unlock(&mtx); // 臨界區(qū)數(shù)據(jù)操作完畢,釋放互斥鎖。
    }
    pthread_cleanup_pop(0);
    return 0;
}

int main(void)
{
    pthread_t tid;
    int i;
    struct node *p;

    /* 子線程會一直等待資源,類似生產(chǎn)者和消費(fèi)者,但是這里的消費(fèi)者可以是多個(gè)消費(fèi)者,
    * 而不僅僅支持普通的單個(gè)消費(fèi)者,這個(gè)模型雖然簡單,但是很強(qiáng)大。*/
    pthread_create(&tid, NULL, thread_func, NULL);
    sleep(1);
    for (i = 0; i < 10; i++)
    {
        p = (struct node*)malloc(sizeof(struct node));
        p->n_number = i;
        pthread_mutex_lock(&mtx); // 需要操作head這個(gè)臨界資源,先加鎖。
        p->n_next = head;
        head = p;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mtx); //解鎖

        sleep(1);
    }

    printf("thread 1 wanna end the line.So cancel thread 2.\n");

    /* 關(guān)于pthread_cancel,有一點(diǎn)額外的說明,它是從外部終止子線程,子線程會在最近的取消點(diǎn),
    * 退出線程,而在我們的代碼里,最近的取消點(diǎn)肯定就是pthread_cond_wait()了。*/

    pthread_cancel(tid);
    pthread_join(tid, NULL);

    printf("All done -- exiting\n");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85

可以看出,等待條件變量信號的用法約定一般是這樣的:

...
pthread_mutex_lock(&mutex);
...
pthread_cond_wait (&cond, &mutex);
...
pthread_mutex_unlock (&mutex);
...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

相信很多人都會有這個(gè)疑問:為什么pthread_cond_wait需要的互斥鎖不在函數(shù)內(nèi)部定義,而要使用戶定義的呢?現(xiàn)在沒有時(shí)間研究 pthread_cond_wait 的源代碼,帶著這個(gè)問題對條件變量的用法做如下猜測,希望明白真相看過源代碼的朋友不吝指正。

  1. pthread_cond_wait 和 pthread_cond_timewait 函數(shù)為什么需要互斥鎖?因?yàn)椋簵l件變量是線程同步的一種方法,這兩個(gè)函數(shù)又是等待信號的函數(shù),函數(shù)內(nèi)部一定有須要同步保護(hù)的數(shù)據(jù)。
  2. 使用用戶定義的互斥鎖而不在函數(shù)內(nèi)部定義的原因是:無法確定會有多少用戶使用條件變量,所以每個(gè)互斥鎖都須要動態(tài)定義,而且管理大量互斥鎖的開銷太大,使用用戶定義的即靈活又方便,符合UNIX哲學(xué)的編程風(fēng)格(隨便推薦閱讀《UNIX編程哲學(xué)》這本好書?。?。
  3. 好了,說完了1和2,我們來自由猜測一下 pthread_cond_wait 函數(shù)的內(nèi)部結(jié)構(gòu)吧:
  int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
   {
      if(沒有條件信號)
      {
         (1)pthread_mutex_unlock (mutex); // 因?yàn)橛脩粼诤瘮?shù)外面已經(jīng)加鎖了(這是使用約定),但是在沒有信號的情況下為了讓其他線程也能等待cond,必須解鎖。
         (2) 阻塞當(dāng)前線程,等待條件信號(當(dāng)然應(yīng)該是類似于中斷觸發(fā)的方式等待,而不是軟件輪詢的方式等待)... 有信號就繼續(xù)執(zhí)行后面。
         (3) pthread_mutex_lock (mutex); // 因?yàn)橛脩粼诤瘮?shù)外面要解鎖(這也是使用約定),所以要與1呼應(yīng)加鎖,保證用戶感覺依然是自己加鎖、自己解鎖。
      }      
      ...
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

三、 信號量

 如同進(jìn)程一樣,線程也可以通過信號量來實(shí)現(xiàn)通信,雖然是輕量級的。
線程使用的基本信號量函數(shù)有四個(gè):

  #include <semaphore.h>
  • 1

1 . 初始化信號量

   int sem_init (sem_t *sem , int pshared, unsigned int value);
  • 1

參數(shù):
sem - 指定要初始化的信號量;
pshared - 信號量 sem 的共享選項(xiàng),linux只支持0,表示它是當(dāng)前進(jìn)程的局部信號量;
value - 信號量 sem 的初始值。

2 . 信號量值加1
給參數(shù)sem指定的信號量值加1。

     int sem_post(sem_t *sem);
  • 1

3 . 信號量值減1
給參數(shù)sem指定的信號量值減1。

     int sem_wait(sem_t *sem);
  • 1

如果sem所指的信號量的數(shù)值為0,函數(shù)將會等待直到有其它線程使它不再是0為止。

4 . 銷毀信號量
銷毀指定的信號量。

  int sem_destroy(sem_t *sem);
  • 1

 示例代碼:

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

#define return_if_fail(p) if((p) == 0){printf ("[%s]:func error!\n", __func__);return;}

typedef struct _PrivInfo
{
    sem_t s1;
    sem_t s2;
    time_t end_time;
}PrivInfo;

static void info_init (PrivInfo* prifo);
static void info_destroy (PrivInfo* prifo);
static void* pthread_func_1 (PrivInfo* prifo);
static void* pthread_func_2 (PrivInfo* prifo);

int main (int argc, char** argv)
{
    pthread_t pt_1 = 0;
    pthread_t pt_2 = 0;
    int ret = 0;
    PrivInfo* prifo = NULL;
    prifo = (PrivInfo* )malloc (sizeof (PrivInfo));

    if (prifo == NULL) {
        printf ("[%s]: Failed to malloc priv.\n");
        return -1;
    }

    info_init (prifo);
    ret = pthread_create (&pt_1, NULL, (void*)pthread_func_1, prifo);
    if (ret != 0) {
        perror ("pthread_1_create:");
    }

    ret = pthread_create (&pt_2, NULL, (void*)pthread_func_2, prifo);
    if (ret != 0) {
        perror ("pthread_2_create:");
    }

    pthread_join (pt_1, NULL);
    pthread_join (pt_2, NULL);
    info_destroy (prifo);
    return 0;
}

static void info_init (PrivInfo* prifo)
{
    return_if_fail (prifo != NULL);
    prifo->end_time = time(NULL) + 10;
    sem_init (&prifo->s1, 0, 1);
    sem_init (&prifo->s2, 0, 0);
    return;
}

static void info_destroy (PrivInfo* prifo)
{
    return_if_fail (prifo != NULL);
    sem_destroy (&prifo->s1);
    sem_destroy (&prifo->s2);
    free (prifo);
    prifo = NULL;
    return;
}

static void* pthread_func_1 (PrivInfo* prifo)
{
    return_if_fail (prifo != NULL);
    while (time(NULL) < prifo->end_time)
    {
        sem_wait (&prifo->s2);
        printf ("pthread1: pthread1 get the lock.\n");
        sem_post (&prifo->s1);
        printf ("pthread1: pthread1 unlock\n");
        sleep (1);
    }
    return;
}

static void* pthread_func_2 (PrivInfo* prifo)
{
    return_if_fail (prifo != NULL);
    while (time (NULL) < prifo->end_time)
    {
        sem_wait (&prifo->s1);
        printf ("pthread2: pthread2 get the unlock.\n");
        sem_post (&prifo->s2);
        printf ("pthread2: pthread2 unlock.\n");
        sleep (1);
    }
    return;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98

四 讀寫鎖
4.1 注意事項(xiàng)

  • 1.如果一個(gè)線程用讀鎖鎖定了臨界區(qū),那么其他線程也可以用讀鎖來進(jìn)入臨界區(qū),這樣就可以多個(gè)線程并行操作。但這個(gè)時(shí)候,如果再進(jìn)行寫鎖加鎖就會發(fā)生阻塞,寫鎖請求阻塞后,后面如果繼續(xù)有讀鎖來請求,這些后來的讀鎖都會被阻塞!這樣避免了讀鎖長期占用資源,防止寫鎖饑餓!
  • 2.如果一個(gè)線程用寫鎖鎖住了臨界區(qū),那么其他線程不管是讀鎖還是寫鎖都會發(fā)生阻塞!

4.2 常用接口
1. 初始化:

int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
  • 1
  1. 讀寫加鎖
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

3.銷毀鎖

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
  • 1

應(yīng)用實(shí)例:

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

/* 初始化讀寫鎖 */
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
/* 全局資源 */
int global_num = 10;

void err_exit(const char *err_msg)
{
 printf("error:%s\n", err_msg);
 exit(1);
}

/* 讀鎖線程函數(shù) */
void *thread_read_lock(void *arg)
{
 char *pthr_name = (char *)arg;

 while (1)
 {
     /* 讀加鎖 */
     pthread_rwlock_rdlock(&rwlock);

     printf("線程%s進(jìn)入臨界區(qū),global_num = %d\n", pthr_name, global_num);
     sleep(1);
     printf("線程%s離開臨界區(qū)...\n", pthr_name);

     /* 讀解鎖 */
     pthread_rwlock_unlock(&rwlock);

     sleep(1);
 }

 return NULL;
}

/* 寫鎖線程函數(shù) */
void *thread_write_lock(void *arg)
{
 char *pthr_name = (char *)arg;

 while (1)
 {
     /* 寫加鎖 */
     pthread_rwlock_wrlock(&rwlock);

     /* 寫操作 */
     global_num++;
     printf("線程%s進(jìn)入臨界區(qū),global_num = %d\n", pthr_name, global_num);
     sleep(1);
     printf("線程%s離開臨界區(qū)...\n", pthr_name);

     /* 寫解鎖 */
     pthread_rwlock_unlock(&rwlock);

     sleep(2);
 }

 return NULL;
}

int main(void)
{
 pthread_t tid_read_1, tid_read_2, tid_write_1, tid_write_2;

 /* 創(chuàng)建4個(gè)線程,2個(gè)讀,2個(gè)寫 */
 if (pthread_create(&tid_read_1, NULL, thread_read_lock, "read_1") != 0)
     err_exit("create tid_read_1");

 if (pthread_create(&tid_read_2, NULL, thread_read_lock, "read_2") != 0)
     err_exit("create tid_read_2");

 if (pthread_create(&tid_write_1, NULL, thread_write_lock, "write_1") != 0)
     err_exit("create tid_write_1");

 if (pthread_create(&tid_write_2, NULL, thread_write_lock, "write_2") != 0)
     err_exit("create tid_write_2");

 /* 隨便等待一個(gè)線程,防止main結(jié)束 */
 if (pthread_join(tid_read_1, NULL) != 0)
     err_exit("pthread_join()");

 return 0;
}

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    日本女人亚洲国产性高潮视频| 日韩精品毛片视频免费看| 日本高清一区免费不卡| 亚洲视频一区自拍偷拍另类 | 亚洲视频在线观看你懂的| 在线欧洲免费无线码二区免费| 免费特黄欧美亚洲黄片| 青青操日老女人的穴穴| 中文字幕一区二区三区大片| 亚洲欧美日韩在线中文字幕| 日韩一级毛一欧美一级乱| 日韩精品在线观看一区| 99亚洲综合精品成人网色播| 欧美综合色婷婷欧美激情| 午夜久久精品福利视频| 麻豆蜜桃星空传媒在线观看| 色偷偷偷拍视频在线观看| 99久久无色码中文字幕免费| 九九久久精品久久久精品| 国产又猛又大又长又粗| 欧美大胆女人的大胆人体| 国产伦精品一区二区三区高清版| 亚洲午夜福利视频在线| 黄色av尤物白丝在线播放网址| 亚洲中文字幕在线观看黑人| 成人精品视频在线观看不卡| 天堂网中文字幕在线观看| 日韩特级黄色大片在线观看| 色哟哟哟在线观看视频| 视频一区中文字幕日韩| 日本一二三区不卡免费| 日韩午夜福利高清在线观看| 午夜精品国产精品久久久| 日本淫片一区二区三区| 亚洲中文字幕熟女丝袜久久| 日本办公室三级在线观看| 国产日韩欧美国产欧美日韩| 黄色片一区二区在线观看| 亚洲中文字幕剧情在线播放| 欧美日韩国产精品黄片| 国产欧美日韩综合精品二区|