Linux--线程互斥量与条件变量

一:.互斥量(mutex)

1.基本概念

  • 在线程之间,因为线程组内所有线程共享进程的地址空间,所以对于每个线程来说,它的绝大多数资源都是与其他线程共享的 ,所以在多线程程序中,极有可能因为多个线程同时访问临界资源,而造成数据的“二义”性(不一致)问题,所以这里就引入了同步与互斥机制用来保护临界资源。
    这里写图片描述
    这里写图片描述

造成这种原因可能因为以下几点:

  • if语句半段条件为真后,代码可能并发切换到其他线程
  • –ticket操作本身就不是一个原字操作。
  • 要解决这些问题,就必须要有一把”锁“来保证每个线程访问临界资源时互斥的,即任何时间点,临界区访问临界资源的时候,有且仅有一个线程访问。Linux提供的这把锁叫互斥量。

2.相关接口

初始化互斥量:

  • 方法1:静态分配pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
  • 方法2:动态分配int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);//第一个为需要初始化的互斥量的地址, 第二个NULL。

销毁会互斥量:

  • int pthread_mutex_destroy(pthread_mutex_t *mutex);//注:静态分配的互斥量不需要销毁。

互斥量加锁和解锁:

  • int pthread_mutex_lock(pthread_mutex_t *mutex);
  • int pthread_mutex_unlock(pthread_mutex_t *mutex);//成功返回0,失败返回错误号
    注:其他线程已经锁定互斥量,或者存在其他线程同时申请互斥量,但没有竞争到互斥量,那么pthread_lock调用就会陷入阻塞,等待互斥量解锁。

这里写图片描述

二:条件变量

1.基本概念:

  • 条件变量是为了实现多个线程可以同步,即多个线程可以协同高效的工作。

2.相关接口:

  • int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);//第一个参数为条件变量,第二个参数为互斥锁。这个函数要干两件事,一是在该条件变量下等待,二是在等待期间释放互斥锁,当被signal或其他方式唤醒时,要重新获得锁,并且从等待处继续执行。
  • int pthread_cond_signal(pthread_cond_t *cond);//在当前条件变量下唤醒某个线程

3.生产者消费者模型:

这里写图片描述

小案列:

  • 一个生产者线程和一个消费者线程,生产者线程向全局链表中插入节点,消费者线程从全局链表中拿走节点,这里为了实现生产者插入一个节点,消费者就会拿掉一个节点,首先必须用互斥量保证两个线程之间互斥,但是有互斥还不够,还需要在生产者生产一个节点之后不能再生产,而是通知消费者消费;消费者发现链表为空不能再去消费而是“通知”生产者生产节点。
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述

注:生产者与消费者模型一般都符合3,2,1规则

  • 3种关系:(生产者与生产者–互斥关系)(消费者与消费者–互斥关系)(生产者与消费者–互斥与同步关系)
  • 2个角色:生产者、消费者角色
  • 1个”交易“场所–上面的案例中交易场所就是链表

四:总结

  • 互斥锁就是为了实现线程间互斥衍生的
  • 互斥锁虽然可以保证数据的一致性,可以保证访问临界资源不出现错误,但是,却不能保证两个或多个线程协同时以某种高效的方式协同的,所以就需要信号变量。
  • 互斥本身是多个线程共同竞争一把锁,锁的申请和释放都由锁的持有者去做
  • 同步是一种让多线程可以协同的机制,实现了“你”申请,“我”释放,“你”释放“,”我“申请,本质是在协调线程执行的顺序。

猜你喜欢

转载自blog.csdn.net/virgofarm/article/details/80644765