Chinaunix首页 | 论坛 | 博客
  • 博客访问: 12962
  • 博文数量: 2
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 20
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-16 15:14
个人简介

长久坚持,必见成效。 Bad programmers worry about the code. Good programmers worry about data structures and their relationships. --- Linus Torvals

文章分类
文章存档

2016年(2)

我的朋友
最近访客

分类: LINUX

2016-07-03 11:20:40

一、同步和互斥的概念

    操作系统中涉及到多线程的协调工作,主要关系有两种:同步和互斥。 同步用来解决任务的先后执行顺序,互斥用来解决共享资源的访问竞争。
    同步:又称为直接制约关系,是指多个线程(或者进程)为了合作完成任务,必须严格按照规定的某种先后顺序来执行。在代码结构中表现为,散布在不同线程之间的若干程序片段,它们的运行必须严格按照规定的某种次序来运行,这种先后次序依赖于要完成的特定任务。 
    互斥:又称为间接制约关系,是指系统中的某些共享资源,一次只允许一个线程访问。当一个线程访问临界资源是,其他线程必须等待,即互斥具有排他性。在代码结构中表现为,散布在不同线程之间的若干程序片段,当线程A运行该代码片段时,线程B、C、D…则不能再运行这一代码片段,只有等上一线程运行完改片段后,B线程才可以运行该片段。      
也就是说互斥是两个线程之间不可以同时运行,他们会互相排斥,必须等一个线程运行完毕,另一个才可以运行;而同步也是不能同时运行的,并且要按照一定的先后顺序来访问或者操作共享资源。

二、为什么要使用多线程技术

  • 避免阻塞,单个进程只有一个主线程,当主线程阻塞的时候,整个进程也就阻塞了,表现为APP卡顿了,无法再无响应其他操作。
  • 避免CPU空转,应用程序经常会涉及到网络访问,数据库操作,磁盘IO操作,这些操作的速度比cpu执行指令的速度慢很多,而在等待这些响应时,CPU不能处理新的请求,导致这种单线程的应用程序性能很差。
  • 提升效率,一个进程要独立拥有4DB的虚拟地址空间,而多个线程可以共享同一地址空间,线程的切换比进程的切换要快很多。

三、 Linux中实现线程间同步和互斥的技术

  • 互斥锁:mutex 包含头文件 #include  解决线程互斥问题

    互斥锁是一种用户态和内核态混合机制,需要两个部分合作完成。上面提到的函数并不是直接系统调用,而是glibc的库函数,这些函数在某些情况下(真的产生资源访问竞争的情况)会进行系统调用。mutex是用来防止资源竞争而采取的互斥技术手段,在很多情况下并不存在竞争,所以这种情况下lock和unlock只在用户态完成,不进行系统调用,避免了系统调用的开销。
    初始化:
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_init(pthread_mutex_t *mutex, constpthread_mutexattr_t *mutexattr);
    上锁:
    pthread_mutex_lock(pthread_mutex_t *mutex);
    pthread_mutex_trylock(pthread_mutex_t *mutex);
    pthread_mutex_timedlock(pthread_mutex_t*mutex, const struct timespec *abstime);
    解锁:
    pthread_mutex_unlock(pthread_mutex_t *mutex);
    销毁:
    pthread_mutex_unlock(pthread_mutex_t *mutex);
  • 信号量:semaphore  包含头文件 #include    解决线程同步问题
    信号量是一个特殊的变量,程序对其访问都是原子操作,且只允许对它进行等待(即P(信号变量))和发送(即V(信号变量))信息操作。我们通常通过信号来解决多个进程对同一资源的访问竞争的问题,使在任一时刻只能有一个执行线程访问代码的临界区域,也可以说它是协调进程间的对同一资源的访问权,也就是用于同步进程的。
    初始化:
    sem_init(sem_t *sem, int pshared, unsignedint value);
    申请资源:信号量减1
    sem_wait(sem_t *sem);
    sem_trywait(sem_t*sem);
    释放资源:信号量加1
    sem_post(sem_t *sem);
  • 条件变量:cond 包含头文件 #include  解决线程同步问题
    条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,条件变量常和互斥锁结合使用。使用时,条件变量被用来阻塞一个线程,当条件不满足 时,线程往往解开相应的互斥锁并等待条件变量发生变化。一旦其它的某个线程改变了条件变量,它将通知相应的条件变量**一个或多个正被此条件变量阻塞的线 程。这些线程将重新锁定互斥锁并重新测试条件是否满足。一般说来,条件变量被用来进行线程间的同步. 
    初始化:
    pthread_cond_t qready=PTHREAD_COND_INITIALIZER;
    pthread_cond_init(pthread_cond_t*cond,  constpthread_condattr_t *cond_attr);
    发送信号:
    pthread_cond_signal(pthread_cond_t*cond);
    等待信号:
    pthread_cond_wait(pthread_cond_t*cond,pthread_mutex_t* mutex);
    pthread_cond_timewait(pthread_cond_t*cond,pthread_mutex_t* mutex, conststruct timespec *abstime);
    销毁:
    pthread_cond_destroy(pthread_cond_t*cond);

三、例子和代码

    流水线生产面包,分为装包线程和封口线程。生产面包必须按照先装包再封口的先后顺序,这个顺序操作就是线程间的同步。假设封口需要用到剪刀,两个线程公用一把剪刀,两个线程对剪刀的使用就是互斥操作。
  • 使用互斥锁实现临界资源的互斥访问:三个线程使用同一把剪刀,进行买包封口工作
  1. /*
  2. *@Purpose: 使用互斥锁实现临界资源的互斥访问
  3. *@Author: xulongqiu163@163.com
  4. *@Created:2016-06-14
  5. */

  6. #include<stdio.h>
  7. #include<stdlib.h>
  8. #include<unistd.h>
  9. #include<pthread.h>
  10. #include<errno.h>

  11. #defineSHEAR_LIFE_CNT (5)
  12. #defineUSE_MUTEX

  13. /*declare functions*/
  14. void*sealBagA(void*arg);
  15. void*sealBagB(void*arg);
  16. void*sealBagC(void*arg);

  17. /*globle variable defination*/
  18. typedef structshear
  19. {
  20.         char name[10];
  21.         int lifeCnt;
  22. }sealBagShearT;

  23. sealBagShearT gShear=
  24. {
  25.         .name = "001",
  26.         .lifeCnt =SHEAR_LIFE_CNT
  27. };
  28. #ifdefUSE_MUTEX
  29. pthread_mutex_tgMutex;
  30. #endif

  31. /*main entry point*/
  32. int main(intargc, char** argv)
  33. {
  34.         pthread_tidA, idB,idC;
  35.         int ret;

  36. #ifdefUSE_MUTEX
  37.         /*init the mutex*/
  38.         pthread_mutex_init(&gMutex, NULL);
  39.         printf("init:gMutex.__data.__lock=%d\n",gMutex.__data.__lock);
  40. #endif
  41.         /*create thread A*/
  42.         ret=pthread_create(&idA, NULL, sealBagA,NULL);
  43.         if(ret< 0)
  44.         {
  45.                 perror("create sealBagA:");
  46.                 exit(-1);
  47.         }

  48.         /*create thread B*/
  49.         ret=pthread_create(&idB, NULL, sealBagB,NULL);
  50.         if(ret< 0)
  51.         {
  52.                 perror("create sealBagB:");
  53.                 exit(-1);
  54.         }
  55.         /*create thread C*/
  56.         ret=pthread_create(&idC, NULL, sealBagC,NULL);
  57.         if(ret< 0)
  58.         {
  59.                 perror("create sealBagC:");
  60.                 exit(-1);
  61.         }

  62.         /*wait sealBagA thread run over*/
  63.         pthread_join(idA, NULL);
  64.         /*wait sealBagB thread run over*/
  65.         pthread_join(idB, NULL);
  66.         /*wait sealBagC thread run over*/
  67.         pthread_join(idC, NULL);

  68.         return 0;
  69. }

  70. /*sealBagA thread*/
  71. void*sealBagA(void*arg)
  72. {
  73.         while(1)
  74.         {
  75.         #ifdef USE_MUTEX
  76.                 /*lock*/
  77.                 printf("A try to get mutex\n");
  78.                 pthread_mutex_lock(&gMutex);
  79.                 printf("lockA:gMutex.__data.__lock=%d\n",gMutex.__data.__lock);
  80.   #endif
  81.                 if(gShear.lifeCnt > 0)
  82.                 {
  83.                         usleep(1000);
  84.                         printf("workerA is using shear:%s, available life=%d\n", gShear.name, gShear.lifeCnt);
  85.                         gShear.lifeCnt--;

  86.                 #ifdef USE_MUTEX
  87.                         /*unlock*/
  88.                         pthread_mutex_unlock(&gMutex);
  89.                         printf("unlockA:gMutex.__data.__lock=%d\n",gMutex.__data.__lock);
  90.     #endif
  91.                 }
  92.                 else
  93.                 {
  94.                         printf("workerA want to use shear:%s, but it does not work\n", gShear.name);
  95.                 #ifdef USE_MUTEX
  96.                         /*unlock*/
  97.                         pthread_mutex_unlock(&gMutex);
  98.                         printf("unlockA:gMutex.__data.__lock=%d\n",gMutex.__data.__lock);
  99.     #endif
  100.                         break;
  101.                 }
  102.                 pthread_yield();
  103.         }
  104.         return (void*)0;
  105. }

  106. /*sealBagB thread*/
  107. void*sealBagB(void*arg)
  108. {
  109.         while(1)
  110.         {
  111.         #ifdef USE_MUTEX
  112.                 /*lock*/
  113.                 printf("B try to mutex\n");
  114.                 pthread_mutex_lock(&gMutex);
  115.                 printf("lockB:gMutex.__data.__lock=%d\n",gMutex.__data.__lock);
  116.         #endif

  117.                 if(gShear.lifeCnt > 0)
  118.                 {
  119.                         usleep(1000);
  120.                         printf("workerB is using shear:%s, available life=%d\n", gShear.name, gShear.lifeCnt);
  121.                         gShear.lifeCnt--;
  122.                 #ifdef USE_MUTEX
  123.                         pthread_mutex_unlock(&gMutex);
  124.                         printf("unlockB:gMutex.__data.__lock=%d\n",gMutex.__data.__lock);
  125.                 #endif
  126.                 }
  127.                 else
  128.                 {
  129.                         printf("workerB want to use shear:%s, but it does not work\n", gShear.name);
  130.                 #ifdef USE_MUTEX
  131.                         /*unlock*/
  132.                         pthread_mutex_unlock(&gMutex);
  133.                         printf("unlockB:gMutex.__data.__lock=%d\n",gMutex.__data.__lock);
  134.                 #endif
  135.                         break;
  136.                 }
  137.                 pthread_yield();
  138.         }
  139.   return(void*)0;
  140. }
  141. /*sealBagC thread*/
  142. void*sealBagC(void*arg)
  143. {
  144.         while(1)
  145.         {
  146.         #ifdef USE_MUTEX
  147.                 /*lock*/
  148.                 printf("C try to mutex\n");
  149.                 pthread_mutex_lock(&gMutex);
  150.                 printf("lockC:gMutex.__data.__lock=%d\n",gMutex.__data.__lock);
  151.         #endif

  152.                 if(gShear.lifeCnt > 0)
  153.                 {
  154.                         usleep(1000);
  155.                         printf("workerC is using shear:%s, available life=%d\n", gShear.name, gShear.lifeCnt);
  156.                         gShear.lifeCnt--;
  157.                 #ifdef USE_MUTEX
  158.                         pthread_mutex_unlock(&gMutex);
  159.                         printf("unlockC:gMutex.__data.__lock=%d\n",gMutex.__data.__lock);
  160.                 #endif
  161.                 }
  162.                 else
  163.                 {
  164.                         printf("workerC want to use shear:%s, but it does not work\n", gShear.name);
  165.                 #ifdef USE_MUTEX
  166.                         /*unlock*/
  167.                         pthread_mutex_unlock(&gMutex);
  168.                         printf("unlockC:gMutex.__data.__lock=%d\n",gMutex.__data.__lock);
  169.                 #endif
  170.                         break;
  171.                 }
  172.                 pthread_yield();
  173.         }
  174.   return(void*)0;
  175. }
  1. result:
  2. init:gMutex.__data.__lock=0
  3. C try to mutex
  4. lockC:gMutex.__data.__lock=1
  5. B try to mutex
  6. A try to get mutex
  7. workerC is using shear:001, available life=5
  8. unlockC:gMutex.__data.__lock=0
  9. lockB:gMutex.__data.__lock=2
  10. C try to mutex
  11. workerB is using shear:001, available life=4
  12. unlockB:gMutex.__data.__lock=0
  13. lockA:gMutex.__data.__lock=2
  14. B try to mutex
  15. workerA is using shear:001, available life=3
  16. unlockA:gMutex.__data.__lock=0
  17. lockC:gMutex.__data.__lock=2
  18. A try to get mutex
  19. workerC is using shear:001, available life=2
  20. unlockC:gMutex.__data.__lock=0
  21. lockB:gMutex.__data.__lock=2
  22. C try to mutex
  23. workerB is using shear:001, available life=1
  24. lockA:gMutex.__data.__lock=2
  25. workerA want to use shear:001, but it does not work
  26. unlockA:gMutex.__data.__lock=0
  27. lockC:gMutex.__data.__lock=2
  28. workerC want to use shear:001, but it does not work
  29. unlockC:gMutex.__data.__lock=0
  30. unlockB:gMutex.__data.__lock=0
  31. B try to mutex
  32. lockB:gMutex.__data.__lock=1
  33. workerB want to use shear:001, but it does not work
  34. unlockB:gMutex.__data.__lock=0
  • 使用信号量实现线程间的同步:装面包和封口两个线程协调工作,先装面包,再封口
  1. /*
  2. *@Purpose: 使用信号量实现线程间的同步
  3. *@Author: xulongqiu163@163.com
  4. *@Created:2016-06-14
  5. */

  6. #include<stdio.h>
  7. #include<stdlib.h>
  8. #include<unistd.h>
  9. #include<pthread.h>
  10. #include<errno.h>
  11. #include<semaphore.h>

  12. #defineBREAD_BAG_CNT (5)
  13. #undefUSE_SEM
  14. #defineUSE_SEM

  15. /*declare functions*/
  16. void*sealBag(void*arg);
  17. void*setBread(void*arg);
  18. int breadBagInit(intstartNum);

  19. typedef enumbagStatus
  20. {
  21.         BAG_EMPTY= 0,
  22.         BAG_SET,
  23.         BAG_SEAL
  24. }BAG_STATUS_T;

  25. typedef structbreadBag
  26. {
  27.         int number;
  28.   BAG_STATUS_T status;
  29. }BREAD_BAG_T;

  30. BREAD_BAG_TgBreadBag[BREAD_BAG_CNT];
  31. #ifdefUSE_SEM
  32. sem_t gSemA, gSemB;
  33. #endif
  34. /*main entry point*/
  35. int main(intargc, char** argv)
  36. {
  37.         pthread_tidA, idB;
  38.         int ret =0;

  39. #ifdefUSE_SEM
  40.         /*A sem init value 1*/
  41.   ret = sem_init(&gSemA, 0, 0);
  42.         /*B sem init value 0*/
  43.   ret += sem_init(&gSemB, 0, 1);
  44.         if( 0)
  45.         {
  46.                 perror("sem_init:");
  47.         }
  48. #endif
  49.   /*initbags*/
  50.         ret= breadBagInit(1);
  51.         printf("init bread %d bags\n", ret);

  52.         /*create thread sealBag*/
  53.         ret=pthread_create(&idA, NULL, sealBag, NULL);
  54.         if(ret< 0)
  55.         {
  56.                 perror("create sealBag:");
  57.         }

  58.         /*create thread B*/
  59.         ret=pthread_create(&idB, NULL, setBread,NULL);
  60.         if(ret< 0)
  61.         {
  62.                 perror("create setBread:");
  63.         }

  64.         /*wait sealBag thread run over*/
  65.         pthread_join(idA, NULL);
  66.         /*wait setBread thread run over*/
  67.         pthread_join(idB, NULL);

  68.         printf("The machine producted %d bags bread totally\n", BREAD_BAG_CNT);
  69.         return 0;
  70. }

  71. int breadBagInit(intstartNum)
  72. {
  73.         int i =0;
  74.         for(;i < BREAD_BAG_CNT;i++)
  75.         {
  76.                 gBreadBag.number = startNum++;
  77.                 gBreadBag.status = BAG_EMPTY;
  78.         }

  79.         return i;
  80. }

  81. /*sealBag thread*/
  82. void*sealBag(void*arg)
  83. {
  84.         int sealedBags = 0;
  85.         while(1)
  86.         {
  87.         #ifdef USE_SEM
  88.                 /*P operation value-1*/
  89.                 sem_wait(&gSemA);
  90.         #endif

  91.                 if(sealedBags< BREAD_BAG_CNT)
  92.                 {
  93.                         usleep(1000);
  94.                         gBreadBag[sealedBags].status= BAG_SEAL;
  95.                         printf("bag:%d has been sealed\n",gBreadBag[sealedBags].number);
  96.                         sealedBags++;
  97.                 #ifdef USE_SEM
  98.                         /*V operation value+1*/
  99.                         sem_post(&gSemB);
  100.                 #endif
  101.                 }
  102.                 else
  103.                 {
  104.                         printf("All the bags have been sealed\n");
  105.                 #ifdef USE_SEM
  106.                         /*V operation value+1*/
  107.                         sem_post(&gSemB);
  108.                 #endif
  109.                         break;
  110.                 }
  111.         }
  112.         return (void*)0;
  113. }

  114. /*setBread thread*/
  115. void*setBread(void*arg)
  116. {
  117.         int setBags = 0;
  118.         while(1)
  119.         {
  120.         #ifdef USE_SEM
  121.                 /*p operation value-1*/
  122.                 sem_wait(&gSemB);
  123.         #endif
  124.                 if(setBags< BREAD_BAG_CNT)
  125.                 {
  126.                         usleep(1000);
  127.                         if(gBreadBag[setBags].status== BAG_SEAL)
  128.                         {
  129.                                 printf("bag:%d has been sealed without set\n", gBreadBag[setBags].number);
  130.                         }
  131.                         else
  132.                         {
  133.                                 gBreadBag[setBags].status= BAG_SET;
  134.                                 printf("bag:%d has been set\n",gBreadBag[setBags].number);
  135.                         }
  136.                         setBags++;
  137.                 #ifdef USE_SEM
  138.                         /*V operation value+1*/
  139.                         sem_post(&gSemA);
  140.                 #endif
  141.                 }
  142.                 else
  143.                 {
  144.                         printf("All the bags have been set\n");
  145.                 #ifdef USE_SEM
  146.                         /*V operation value+1*/
  147.                         sem_post(&gSemA);
  148.                 #endif
  149.                         break;
  150.                 }
  151.         }
  152.   return(void*)0;
  153. }
  1. result:
  2. init bread 5 bags
  3. bag:1 has been set
  4. bag:1 has been sealed
  5. bag:2 has been set
  6. bag:2 has been sealed
  7. bag:3 has been set
  8. bag:3 has been sealed
  9. bag:4 has been set
  10. bag:4 has been sealed
  11. bag:5 has been set
  12. bag:5 has been sealed
  13. All the bags have been set
  14. All the bags have been sealed
  15. The machine producted 5 bags bread totally
  • 使用条件变量和互斥锁实现线程间的同步:装面包和封口两个线程协调工作,先装面包,再封口
  1. /*
  2.  *@Purpose: 使用条件变量实现线程间的同步
  3.  *@Author: xulongqiu163@163.com
  4.  *@Created: 2016-06-14
  5. */

  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <unistd.h>
  9. #include <pthread.h>
  10. #include <errno.h>

  11. #define BREAD_BAG_CNT (5)
  12. #undef USE_COND
  13. #define USE_COND

  14. /*declare functions*/
  15. void* sealBag(void* arg);
  16. void* setBread(void* arg);
  17. int breadBagInit(int startNum);

  18. typedef enum bagStatus
  19. {
  20.     BAG_EMPTY = 0,
  21.     BAG_SET,
  22.     BAG_SEAL
  23. }BAG_STATUS_T;

  24. typedef struct breadBag
  25. {
  26.     int number;
  27.   BAG_STATUS_T status;    
  28. }BREAD_BAG_T;

  29. BREAD_BAG_T gBreadBag[BREAD_BAG_CNT];
  30. int gFinishBags = 0;
  31. #ifdef USE_COND
  32. pthread_mutex_t mxt;
  33. pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  34. #endif
  35. /*main entry point*/
  36. int main(int argc, char** argv)
  37. {
  38.     pthread_t idA, idB;
  39.     int ret = 0;

  40. #ifdef USE_COND
  41.     pthread_mutex_init(&mxt, NULL);
  42. #endif
  43.   /*init bags*/
  44.     ret = breadBagInit(1);
  45.     printf("init bread %d bags\n", ret);

  46.     /*create thread sealBag*/
  47.     ret=pthread_create(&idA, NULL, sealBag, NULL);
  48.     if(ret < 0)
  49.     {
  50.         perror("create sealBag:");
  51.     }

  52.     /*create thread B*/
  53.     ret=pthread_create(&idB, NULL, setBread, NULL);
  54.     if(ret < 0)
  55.     {
  56.         perror("create setBread:");
  57.     }

  58.     /*wait sealBag thread run over*/
  59.     pthread_join(idA, NULL);
  60.     /*wait setBread thread run over*/
  61.     pthread_join(idB, NULL);

  62.     printf("The machine producted %d bags bread totally\n", BREAD_BAG_CNT);
  63.     return 0;
  64. }

  65. int breadBagInit(int startNum)
  66. {
  67.     int i = 0;
  68.     for(; i < BREAD_BAG_CNT; i++)
  69.     {
  70.         gBreadBag[i].number = startNum++;
  71.         gBreadBag[i].status = BAG_EMPTY;
  72.     }

  73.     return i;
  74. }

  75. /*sealBag thread*/
  76. void* sealBag(void* arg)
  77. {
  78.     while(1)
  79.     {
  80.     #ifdef USE_COND
  81.         pthread_mutex_lock(&mxt);
  82.     #endif
  83.         if(gFinishBags < BREAD_BAG_CNT)
  84.         {
  85.             if(gBreadBag[gFinishBags].status == BAG_EMPTY)
  86.             {
  87.                 printf("try to seal bag:%d\n",gBreadBag[gFinishBags].number);
  88.             #ifdef USE_COND
  89.                 pthread_cond_wait(&cond, &mxt);
  90.             #endif
  91.             }
  92.             else
  93.             {
  94.                 usleep(300);
  95.                 gBreadBag[gFinishBags].status = BAG_SEAL;
  96.                 printf("bag:%d has been sealed\n",gBreadBag[gFinishBags].number);
  97.                 gFinishBags++;
  98.             #ifdef USE_COND
  99.                 pthread_cond_signal(&cond);
  100.             #endif
  101.             }
  102.         #ifdef USE_COND
  103.             pthread_mutex_unlock(&mxt);
  104.         #endif
  105.         }
  106.         else
  107.         {
  108.             printf("All the bags have been sealed\n");
  109.         #ifdef USE_COND
  110.             pthread_mutex_unlock(&mxt);
  111.         #endif
  112.             break;
  113.         }
  114.     }
  115.     return (void*)0;
  116. }

  117. /*setBread thread*/
  118. void* setBread(void* arg)
  119. {
  120.     while(1)
  121.     {
  122.     #ifdef USE_COND
  123.         pthread_mutex_lock(&mxt);
  124.     #endif
  125.         if(gFinishBags < BREAD_BAG_CNT)
  126.         {
  127.             if(gBreadBag[gFinishBags].status == BAG_EMPTY)
  128.             {
  129.                 usleep(1000);
  130.                 gBreadBag[gFinishBags].status = BAG_SET;
  131.              printf("bag:%d has been set\n",gBreadBag[gFinishBags].number);
  132.             #ifdef USE_COND
  133.                 pthread_cond_signal(&cond);
  134.             #endif
  135.             }
  136.             else
  137.             {
  138.             #ifdef USE_COND
  139.                 pthread_cond_wait(&cond, &mxt);
  140.             #endif
  141.             }
  142.         #ifdef USE_COND
  143.             pthread_mutex_unlock(&mxt);
  144.         #endif
  145.         }
  146.         else
  147.         {
  148.             printf("All the bags have been set\n");
  149.         #ifdef USE_COND
  150.             pthread_mutex_unlock(&mxt);
  151.         #endif
  152.             break;
  153.         }
  154.     }
  155.   return (void*)0;
  156. }
  1. Result:
  2. init bread 5 bags
  3. bag:1 has been set
  4. bag:1 has been sealed
  5. try to seal bag:2
  6. bag:2 has been set
  7. bag:2 has been sealed
  8. try to seal bag:3
  9. bag:3 has been set
  10. bag:3 has been sealed
  11. try to seal bag:4
  12. bag:4 has been set
  13. bag:4 has been sealed
  14. try to seal bag:5
  15. bag:5 has been set
  16. bag:5 has been sealed
  17. All the bags have been sealed
  18. All the bags have been set
  19. The machine producted 5 bags bread totally



阅读(1101) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:Linux 之mutex 源码分析

给主人留下些什么吧!~~