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个”交易“场所–上面的案例中交易场所就是链表
四:总结
- 互斥锁就是为了实现线程间互斥衍生的
- 互斥锁虽然可以保证数据的一致性,可以保证访问临界资源不出现错误,但是,却不能保证两个或多个线程协同时以某种高效的方式协同的,所以就需要信号变量。
- 互斥本身是多个线程共同竞争一把锁,锁的申请和释放都由锁的持有者去做
- 同步是一种让多线程可以协同的机制,实现了“你”申请,“我”释放,“你”释放“,”我“申请,本质是在协调线程执行的顺序。