Linux线程的同步与互斥机制

举报
王建峰 发表于 2021/11/19 01:32:41 2021/11/19
【摘要】 拥有梦想是一种智力,实现梦想是一种能力。   概述 线程共享同一进程的地址空间,线程间通过全局变量交换数据进行通信。为了避免多个进程同时访问同一个共享资源而引发冲突,多个线程访问共享数据时需要同步或互斥机制 同步机制:指的是多个任务按照约定的先后次序相互配合完成一件事情 互斥机制:一次只允许一个任务...

拥有梦想是一种智力,实现梦想是一种能力。

 

概述

线程共享同一进程的地址空间,线程间通过全局变量交换数据进行通信。为了避免多个进程同时访问同一个共享资源而引发冲突,多个线程访问共享数据时需要同步或互斥机制

同步机制:指的是多个任务按照约定的先后次序相互配合完成一件事情

互斥机制:一次只允许一个任务(进程、线程)访问的共享资源

 

同步机制

信号量:代表某一类资源,其值表示系统中该资源的数量,由信号量来决定线程是继续运行还是阻塞等待。分为无名信号量(基于内存的信号量,本章讨论)和有名信号量。

就比如,我这里是网吧,那现在来了一个人开了一个机子,申请了一个资源,我这里可用电脑数量就会少一,如果有个人走了,关了一个自己,释放了一个资源,我这里可使用的电脑数量就会多一,电脑就可以理解成这个资源,这个初始值是多少呢,这个我们来定,根据需要写就可以

 

信号量是一个受保护的变量,只能通过三种操作来访问

  • 初始化
  • P操作(申请资源)
  • V操作(释放资源)

 

要使用同步机制管理线程,线使用sem_init初始化信号量sem,指定资源的数量。完成任务后使用sem_post,如果要用资源使用sem_post,V操作作用是释放资源,增加空余资源 sem++ ; P操作作用是申请资源,如果sem是0,它就申请不到资源的,就不会执行申请,会等释放后才能申请,申请成功后减少空余资源sem--。

 

初始化信号量

 #include  <semaphore.h>
 int  sem_init(sem_t *sem, int pshared, unsigned int val);

  •  成功时返回0,失败时EOF
  •  sem  指向要初始化的信号量对象
  •  pshared   0 – 线程间   1 – 进程间
  •  val  信号量初值

 

释放资源(V)/申请资源(P)

 #include  <semaphore.h>
 int  sem_wait(sem_t  *sem);       P操作
 int  sem_post(sem_t  *sem);       V操作

  •  成功时返回0,失败时返回EOF
  •  sem  指向要操作的信号量对象

 

示例

函数的功能是,主线程读取我们从终端写入的数据到buf,子线程sem_wait是等待主线程释放资源后进行相关操作。
 


  
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <pthread.h>
  4. char buf[32];
  5. sem_t sem;
  6. void *function(void *arg);
  7. int main(void) {
  8. pthread_t a_thread;
  9. if (sem_init(&sem, 0, 0) < 0) {
  10. perror(“sem_init”); exit(-1);
  11. }
  12. if (pthread_create(&a_thread, NULL, function, NULL) != 0) {
  13. printf(“fail to pthread_create”);
  14. exit(-1);
  15. }
  16. printf(“input ‘quit’ to exit\n”);
  17. do {
  18. fgets(buf, 32, stdin);
  19. sem_post(&sem);
  20. } while (strncmp(buf, “quit”, 4) != 0);
  21. return 0;
  22. }
  23. void *function(void *arg) {
  24. while ( 1 ) {
  25. sem_wait(&sem);
  26. printf(“you enter %d characters\n”, strlen(buf));
  27. }
  28. }

V操作表示已经把这个资源利用过了,释放一个资源;P操作是即将用到一个资源,申请一个资源。
比如一个人关了机子离开网吧,sem(信号量)控制另一个人来开机子。

sem表示资源的数量,释放是增加空余资源 sem++ ; 申请是减少空余资源sem--
这里sem的变化是 开始0 -> 主线程1 -> 子线程0 ->......

 

gcc 编译的时候注意加载库 -pthread

 

 

 

 

互斥机制

 

临界资源: 一次只允许一个任务(进程、线程)访问的共享资源

临界区:访问临界资源的代码

互斥机制:mutex互斥锁,任务访问临界资源前申请锁,访问完后释放锁

 

互斥锁的三种操作

  • 初始化互斥锁
  • 申请锁
  • 释放锁

 

因为,互斥机制一次只允许一个任务(进程、线程)访问的共享资源。通过互斥锁构造这种机制,首先要pthread_mutex_init初始化互斥锁,然后我们在访问临界资源的代码之前用pthread_mutex_lock来给临界区·加锁·,结束再pthread_mutex_unlock释放锁。

 

初始化互斥锁

 #include  <pthread.h>
 int  pthread_mutex_init(pthread_mutex_t *mutex,
       const pthread_mutexattr_t *  attr);

  •  成功时返回0,失败时返回错误码
  •  mutex  指向要初始化的互斥锁对象
  •  attr  互斥锁属性,NULL表示缺省属性

 

申请锁

 #include  <pthread.h>
 int  pthread_mutex_lock(pthread_mutex_t *mutex);

  •  成功时返回0,失败时返回错误码
  •  mutex  指向要初始化的互斥锁对象
  •  如果无法获得锁,任务阻塞

 

释放锁

 #include  <pthread.h>
 int  pthread_mutex_unlock(pthread_mutex_t *mutex);

  •  成功时返回0,失败时返回错误码
  •  mutex  指向要初始化的互斥锁对象
  •  执行完临界区要及时释放锁

 

示例

宏 _LOCK_ 为1表示使用互斥机制,保证主进程与子进程执行到临界区不能被切换,所以 value1 始终等于 value2 !


  
  1. #include <stdio.h>
  2. #include <pthread.h>
  3. unsigned int count, value1, value2;
  4. pthread_mutex_t lock;
  5. void *function(void *arg);
  6. int main(void) {
  7. pthread_t a_thread;
  8. if (pthread_mutex_init(&lock, NULL) != 0) {
  9. printf(“fail to pthread_mutex_init\n”); exit(-1);
  10. }
  11. if (pthread_create(&a_thread, NULL, function, NULL) != 0) {
  12. printf(“fail to pthread_create”); exit(-1);
  13. }
  14. while ( 1 ) {
  15. count++;
  16. #ifdef _LOCK_
  17. pthread_mutex_lock(&lock);
  18. #endif
  19. value1 = count;
  20. value2 = count;
  21. #ifdef _LOCK_
  22. pthread_mutex_unlock(&lock);
  23. #endif
  24. }
  25. return 0;
  26. }
  27. void *function(void *arg) {
  28. while ( 1 ) {
  29. #ifdef _LOCK_
  30. pthread_mutex_lock(&lock);
  31. #endif
  32. if (value1 != value2) {
  33. printf(“value1 = %u, value2 = %u\n”, value1, value2);
  34. usleep(100000);
  35. }
  36. #ifdef _LOCK_
  37. pthread_mutex_unlock(&lock);
  38. #endif
  39. }
  40. return NULL;
  41. }

 

文章来源: blog.csdn.net,作者:hinzer,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/feit2417/article/details/81302501

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。