Linux线程的同步与互斥机制

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

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

概述

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

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

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

同步机制

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

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

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

  • 初始化
  • 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是等待主线程释放资源后进行相关操作。
 


      #include <stdio.h>
      #include <string.h>
      #include <pthread.h>
      char buf[32];
      sem_t  sem;
      void *function(void *arg);
      int main(void) {
       pthread_t  a_thread;
       if (sem_init(&sem, 0,  0) < 0) {
     	perror(“sem_init”);  exit(-1);
        }
       if (pthread_create(&a_thread, NULL, function, NULL) != 0) {
     	printf(“fail to pthread_create”);
     	exit(-1);
        }
       printf(“input ‘quit’ to exit\n”);
       do {
         fgets(buf, 32, stdin);
         sem_post(&sem);
        }  while (strncmp(buf, “quit”, 4) != 0);
       return 0;
      }
      void *function(void *arg) {
        while ( 1 ) {
     	  sem_wait(&sem);
     	  printf(“you enter %d characters\n”, strlen(buf));
         }
      }
  
 

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 !


      #include <stdio.h>
      #include <pthread.h>
      unsigned int count, value1, value2;
      pthread_mutex_t lock;
      void *function(void *arg);
      int main(void) {
       pthread_t  a_thread;
       if (pthread_mutex_init(&lock, NULL) != 0) {
         printf(“fail to pthread_mutex_init\n”);  exit(-1);
        }
       if (pthread_create(&a_thread, NULL, function, NULL) != 0) {
         printf(“fail to pthread_create”);  exit(-1);
        }
       while ( 1 ) {
          count++;
      #ifdef _LOCK_
         pthread_mutex_lock(&lock);
      #endif
          value1 = count;
          value2 = count;
      #ifdef _LOCK_
         pthread_mutex_unlock(&lock);
      #endif
        }
       return 0;
      }
      void *function(void *arg) {
       while ( 1 ) {
      #ifdef _LOCK_
         pthread_mutex_lock(&lock);
      #endif
         if (value1 != value2) {
           printf(“value1 = %u, value2 = %u\n”, value1, value2);
           usleep(100000);
          }
      #ifdef _LOCK_
         pthread_mutex_unlock(&lock);
      #endif
        }
       return  NULL;
      }
  
 

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

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

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

作者其他文章

评论(0

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

    全部回复

    上滑加载中

    设置昵称

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

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

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