经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C 语言 » 查看文章
C语言细致讲解线程同步的集中方式
来源:jb51  时间:2022/5/9 12:22:06  对本文有异议

互斥锁

使用互斥量完成对临界区的资源的加锁操作,使得同一时刻,对一个共享数据的使用只能又一个线程完成

例向屏幕上一次打印abcd四个字母

可以使用的是一个类似锁连的思想 a 加完解开后拿b锁依次类推

  1. #define THRNUM 4
  2. static pthread_mutex_t mut[4];
  3. static int next(int n)
  4. {
  5. if(n + 1 == THRNUM)
  6. return 0;
  7. return n+1;
  8. }
  9. static void* pthreadfunc(void* p)
  10. {
  11. int n =(int)p;
  12. char c = 'a' + (int)p;
  13. while(1)
  14. {
  15. pthread_mutex_lock(mut + n);
  16. write(1,&c,1);
  17. pthread_mutex_unlock(mut + next(n));
  18. }
  19. pthread_exit(NULL);
  20. }
  21. int main()
  22. {
  23. int i,err;
  24. pthread_t tid[THRNUM];
  25. //创建线程
  26. for(i = 0 ; i < THRNUM ;i++){
  27. //初始化锁
  28. pthread_mutex_init(mut + i,NULL);
  29. //加锁
  30. pthread_mutex_lock(mut+i );
  31. err = pthread_create(tid+i,NULL,pthreadfunc,(void*)i );
  32. if(err != 0)
  33. {
  34. fprintf(stderr,"create:%s\n",strerror(err));
  35. exit(1);
  36. }
  37. }
  38. //回收线程
  39. pthread_mutex_unlock(mut + 0);
  40. alarm(5);
  41. for(i = 0 ; i < THRNUM ;i++){
  42. pthread_join(tid+i,NULL);
  43. }
  44. }

条件变量

条件变量并不是锁而是一种阻塞机制,使得我们的程序在某些特定的条件,比如生产者生产达到上限未消费,此时使用条件变量(加上while对条件的判断)来阻塞生产,让生产者消费

  1. #include<stdio.h>
  2. #include<unistd.h>
  3. #include<pthread.h>
  4. #include<stdlib.h>
  5. #include<string.h>
  6. int begnum=0;
  7. static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
  8. static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  9. typedef struct _prodinfo
  10. {
  11. int num;
  12. struct _prodinfo *next;
  13. }prod;
  14. struct _prodinfo* head=NULL;
  15. /* 条件变量可以引起阻塞并非锁
  16. */
  17. void *thr_produce(void*arg)
  18. {
  19. while(1)
  20. {
  21. prod* pd = malloc(sizeof(struct _prodinfo));
  22. pd->num=begnum++;
  23. pthread_mutex_lock(&mut);
  24. pd->next=head;
  25. head=pd;
  26. printf(" -%ld号线程生产%d产品\n",pthread_self(),pd->num);
  27. pthread_mutex_unlock(&mut);
  28. pthread_cond_signal(&cond);
  29. sleep(rand()%4);
  30. }
  31. }
  32. void* thr_con(void* arg)
  33. {
  34. prod* pro=NULL;
  35. while(1)
  36. {
  37. pthread_mutex_lock(&mut);
  38. while(head==NULL)
  39. pthread_cond_wait(&cond,&mut);
  40. pro = head;
  41. head=head->next;
  42. printf(" -%ld号线程消费%d产品\n",pthread_self(),pro->num);
  43. pthread_mutex_unlock(&mut);
  44. free(pro);
  45. sleep(rand()%4);
  46. }
  47. }
  48. int main()
  49. {
  50. pthread_t cid,pid;
  51. int err1=pthread_create(&pid,NULL,thr_produce,NULL);
  52. if(err1)
  53. {
  54. fprintf(stderr,"pthread_creat():%s\n",strerror(err1));
  55. exit(1);
  56. }
  57. int err2=pthread_create(&cid,NULL,thr_con,NULL);
  58. if(err2)
  59. {
  60. fprintf(stderr,"pthread_creat():%s\n",strerror(err1));
  61. exit(1);
  62. }
  63. pthread_join(pid,NULL);
  64. pthread_join(cid,NULL);
  65. }

信号量

介绍以下信号量是进化版的互斥量,允许多个线程访问共享资源与条件变量和互斥量类此的操作,在进程和线程中均可以使用

  1. int sem_init(sem_t *sem, int pshared, unsigned int value);
  2. int sem_destroy(sem_t *sem);
  3. Link with -pthread.

sem为定义的信号量,传出型参数

pshared

  • 0 代表线程信号量
  • 1 代表进程信号量

alue 为定义的信号量个数

  1. int sem_wait(sem_t *sem);
  2. int sem_trywait(sem_t *sem);
  3. int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

申请信号量,申请成功value–,当value为0 则阻塞

  1. int sem_post(sem_t *sem);

释放信号量value++

例 信号量实现生产者消费者模型

  1. sem_t pro_sem,con_sem;
  2. #define semcnt 5
  3. int i=0;
  4. int queue[semcnt];
  5. int beginnum = 100;
  6. void *thr_produce(void*arg)
  7. {
  8. while(1)
  9. {
  10. sem_wait(&pro_sem);//生产者申请资源 pro_sem每被占用一次--一次 当为0时则阻塞
  11. printf("%ld 线程生产了 %d\n",pthread_self(),beginnum);
  12. queue[(i++)%semcnt]= beginnum++;
  13. sem_post(&con_sem);//为消费者的信号量释放资源pro_sem每被释放一次++一次
  14. sleep(rand()%4);
  15. }
  16. return NULL;
  17. }
  18. void* thr_con(void* arg)
  19. {
  20. int i=0;
  21. int num=0;
  22. while(1)
  23. {
  24. sem_wait(&con_sem);
  25. num = queue[(i++)%semcnt];
  26. printf("%ld 线程消费了 %d\n",pthread_self(),num);
  27. sem_post(&pro_sem);
  28. sleep(rand()%3);
  29. }
  30. return NULL;
  31. }
  32. int main()
  33. {
  34. sem_init(&pro_sem,0,semcnt);
  35. sem_init(&con_sem,0,0); //消费者初始默认没有产品
  36. pthread_t tid[2];
  37. int err1=pthread_create(&tid[0],NULL,thr_produce,NULL);
  38. if(err1)
  39. {
  40. fprintf(stderr,"pthread_creat():%s\n",strerror(err1));
  41. exit(1);
  42. }
  43. int err2=pthread_create(&tid[1],NULL,thr_con,NULL);
  44. if(err2)
  45. {
  46. fprintf(stderr,"pthread_creat():%s\n",strerror(err1));
  47. exit(1);
  48. }
  49. pthread_join(tid[0],NULL);
  50. pthread_join(tid[1],NULL);
  51. sem_destroy(&pro_sem);
  52. sem_destroy(&con_sem);
  53. }

读写锁

读写锁 与互斥量类似,但是读写锁允许更高的并行性,其特性为:写独占,读共享

读写锁实质上是一把锁,有不同的状态,写锁的优先级高

读写锁的三种状态

  • 读模式下加锁(读锁)
  • 写模式下加锁(写锁)
  • 不加锁状态

读写锁的特性: 读锁可以共享读的状态,当读锁加上时,阻塞写锁的加锁

即使读锁加上时 后面的 写锁依然会被阻塞,当前面读锁释放时才能加成功

  1. pthread_rwlock_t rwlock =PTHREAD_RWLOCK_INITIALIZER;
  2. int beginum=100;
  3. void*thr_Wr(void*arg)
  4. {
  5. while(1)
  6. {
  7. pthread_rwlock_wrlock(&rwlock);
  8. printf("-写线程--beginum = %d\n",beginum++);
  9. usleep(2000);//模拟占用时间
  10. pthread_rwlock_unlock(&rwlock);
  11. usleep(2000);//简单防止再抢锁的方法但不建议使用
  12. }
  13. return NULL;
  14. }
  15. void*thr_ead(void*arg)
  16. {
  17. while (1)
  18. {
  19. pthread_rwlock_rdlock(&rwlock);
  20. printf("-读读线程--beginum = %d\n",beginum);
  21. usleep(2000);//模拟占用时间
  22. pthread_rwlock_unlock(&rwlock);
  23. usleep(2000);//简单防止再抢锁的方法但不建议使用
  24. }
  25. return NULL;
  26. }
  27. int main()
  28. {
  29. int n=8,i=0;
  30. pthread_t tid[8];
  31. for(i = 0; i<5;i++)
  32. {
  33. pthread_create(&tid[i],NULL,thr_ead,NULL);
  34. }
  35. for(; i<8;i++)
  36. {
  37. pthread_create(&tid[i],NULL,thr_Wr,NULL);
  38. }
  39. for(i = 0; i<8;i++)
  40. {
  41. pthread_join(tid[i],NULL);
  42. }
  43. pthread_rwlock_destroy(&rwlock);
  44. }

到此这篇关于C语言细致讲解线程同步的集中方式的文章就介绍到这了,更多相关C语言线程同步内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号