1 互斥锁

1.1 互斥锁函数

  • pthread_mutex_init:创建互斥锁
  • pthread_mutex_lock:锁定
  • pthread_mutex_unlock:解锁
  • pthread_mutex_destroy:删除互斥锁

1.2 互斥锁示例

  1. #include <pthread.h>
  2. #include <errno.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <sys/types.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. int run_now=1; /*用run_now代表共享资源*/
  9. pthread_mutex_t work_mutex; /*定义互斥量*/
  10. void *thread_function(void *arg)
  11. {
  12. sleep(1);
  13. /*对互斥量加锁*/
  14. if(pthread_mutex_lock(&work_mutex)!=0)
  15. {
  16. perror("Lock failed");
  17. exit(1);
  18. }
  19. else
  20. printf("function lock\n");
  21. for (int i=0; i<5; i++)
  22. {
  23. /*分线程:如果run_now为1就把它修改为1*/
  24. if(run_now==2)
  25. {
  26. printf("function thread is run\n");
  27. run_now=1;
  28. }
  29. else
  30. {
  31. printf("function thread is sleep\n");
  32. sleep(1);
  33. }
  34. }
  35. /*对互斥量解锁*/
  36. if(pthread_mutex_unlock(&work_mutex)!=0)
  37. {
  38. perror("unlock failed");
  39. exit(1);
  40. }
  41. else
  42. printf("function unlock\n");
  43. pthread_exit(NULL);
  44. }
  45. int main()
  46. {
  47. pthread_t a_thread;
  48. if(pthread_mutex_init(&work_mutex,NULL)!=0) /*初始化互斥量*/
  49. {
  50. perror("Mutex init faied");
  51. exit(1);
  52. }
  53. if(pthread_create(&a_thread,NULL,thread_function,NULL)!=0) /*创建新线程*/
  54. {
  55. perror("Thread createion failed");
  56. exit(1);
  57. }
  58. if(pthread_mutex_lock(&work_mutex)!=0) /*对互斥量加锁*/
  59. {
  60. perror("Lock failed");
  61. exit(1);
  62. }
  63. else
  64. printf("main lock\n");
  65. for (int i=0; i<5; i++)
  66. {
  67. if(run_now == 1) /*主线程:如果run_now为1就把它修改为2*/
  68. {
  69. printf("main thread is run\n");
  70. run_now=2;
  71. }
  72. else
  73. {
  74. printf("main thread is sleep\n");
  75. sleep(1);
  76. }
  77. }
  78. if(pthread_mutex_unlock(&work_mutex)!=0) /*对互斥量解锁*/
  79. {
  80. perror("unlock failed");
  81. exit(1);
  82. }
  83. else
  84. printf("main unlock\n");
  85. pthread_join(a_thread,NULL); /*等待子线程结束*/
  86. pthread_mutex_destroy(&work_mutex); /*收回互斥量资源*/
  87. exit(0);
  88. }

2 自旋锁

当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。
减少了不必要的上下文切换,但会加剧CPU消耗

  • pthread_spin_init
  • pthread_spin_destroy
  • pthread_spin_lock
  • pthread_spin_unlock

3 读写锁

  • 读锁之间是共享的:即一个线程持有了读锁之后,其他线程也可以以读的方式持有这个锁
  • 写锁之间是互斥的:即一个线程持有了写锁之后,其他线程不能以读或者写的方式持有这个锁
  • 读写锁之间是互斥的:即一个线程持有了读锁之后,其他线程不能以写的方式持有这个锁

  • Pthread_rwlock_init

  • Pthread_rwlock_destory
  • Pthread_rwlock_rdlock
  • Pthread_rwlock_wrlock
  • Pthread_rwlock_unlock

4 POSIX条件变量

当一个线程互斥的访问某个变量时,需要等待其他线程改变变量状态之后才能访问。这样的变量要设置成条件变量
头文件

  1. #include <pthread.h>

4.1 条件变量函数

  • pthread_cond_init:初始化条件变量
  • pthread_cond_destroy:删除条件变量
  • pthread_cond_wait:在一个指定的条件上等待。具体执行逻辑如下
    • 对第二个参数的互斥锁解锁
    • 等待条件,知道有线程发起条件满足通知
    • 对互斥锁重新加锁
  • pthread_cond_signal:当条件满足时,向指定线程发送通知。如果没有线程wait,通知被丢弃。
  • pthread_cond_broadcast:当条件满足时,向所有线程发送通知

条件变量通常与互斥锁配合使用,条件变量使用规范如下:

  • 等待条件代码

    1. pthread_mutex_lock(&mutex); //锁定互斥量
    2. //这里用while是为了防止虚假唤醒,如果是虚假唤醒,条件并没有改变,需要用while再次判断条件是否满足
    3. while(条件为假)
    4. pthread_cond_wait(cond,mutex);
    5. 修改条件
    6. pthread_mutex_unlock(&mutex);
  • 给线程发送信号代码

    1. pthread_mutex_lock(&mutex);
    2. 设置条件为真
    3. pthread_cond_signal(cond);
    4. pthread_mutex_unlock(&mutex);

    4.2 生产者消费者问题示例

    ```c

    include

    include

    include

    include

    include

    include

    include

define ERR_EXIT(m) \

  1. do \
  2. { \
  3. perror(m); \
  4. exit(EXIT_FAILURE); \
  5. }while(0)

define CONSUMERS_COUNT 2

define PRODUCERS_COUNT 4

pthread_cond_t g_cond; pthread_mutex_t g_mutex;

// 创建的线程ID保存在g_thread中 pthread_t g_thread[CONSUMERS_COUNT+PRODUCERS_COUNT];

int nready=0;

///消费者 void consume(void arg) { //most platforms pointers and longs are the same size, but ints and pointers often are not the same size on 64bit platforms int num = (long)arg; while(1) { pthread_mutex_lock(&g_mutex); while(nready == 0) { printf(“(%d)begin wait a condition….\n”,num); pthread_cond_wait(&g_cond,&g_mutex); } printf(“(%d) end wait a condition….\n”,num); printf(“(%d) begin consume product ….\n”,num); —nready; printf(“(%d) end consume product ….\n”,num); pthread_mutex_unlock(&g_mutex); sleep(1); } return NULL; }

//// 生产者 void produce(void arg) { //most platforms pointers and longs are the same size, but ints and pointers often are not the same size on 64bit platforms int num = (long)arg; while(1) { pthread_mutex_lock(&g_mutex); printf(“ (%d) begin produce product …\n”,num); ++nready; printf(“ (%d) end produce product….\n”,num); pthread_cond_signal(&g_cond); printf(“ (%d) signal \n”,num); pthread_mutex_unlock(&g_mutex); sleep(5); } return NULL; }

int main(void ) { //初始化互斥锁 pthread_mutex_init(&g_mutex,NULL); //初始化条件变量 pthread_cond_init(&g_cond,NULL);

  1. /// 创建消费者线程
  2. for(int i=0; i<CONSUMERS_COUNT; i++)
  3. pthread_create(&g_thread[i],NULL,consume,(void*)i);
  4. sleep(1);
  5. /// 创建生产者线程
  6. for(int i=0; i<PRODUCERS_COUNT; i++)
  7. pthread_create(&g_thread[CONSUMERS_COUNT+i],NULL,produce,(void*)i);
  8. // 等待线程的结束
  9. for(int i=0; i<CONSUMERS_COUNT+PRODUCERS_COUNT; i++)
  10. pthread_join(g_thread[i],NULL);
  11. //销毁互斥锁和条件变量
  12. pthread_mutex_destroy(&g_mutex);
  13. pthread_cond_destroy(&g_cond);
  14. return 0;

} ```

5 信号量

语雀内容