【Linux】线程同步与互斥

线程互斥相关概念

临界资源:多线程执行流共享的资源就叫做临界资源。
临界区:每个线程内部,访问临界资源的代码,就叫做临界区。
互斥:任何时刻,互斥保证有且只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用。
原子性:不会被任何调度机制打断的操作,该操作只有两态,要么完成,要么未完成。

大部分情况下,线程使⽤的数据都是局部变量,变量的地址空间在线程栈空间内,这种情况,变量归属单个线程,其他线程⽆法获得这种变量。但有时候,很多变量都需要在线程间共享,这样的变量称为共享变量,也就是临界资源,可以通过数据的共享,完成线程之间的交互。多个线程并发的操作共享的变量,就会出现问题。

要解决上面的问题,需要做到上面三点:
代码必须要有互斥行为:当代码进入临界区执行时,不允许其他线程进入该临界区。
如果多个线程同时要求执行临界区的代码,并且临界区没有线程在执行,那么只能允许一个线程进入该临界区。
如果线程不在临界区中执行,那么该线程不能阻止其他线程进入临界区。

要做到这三点,本质上就是需要一把锁。Linux上提供的这把锁叫互斥量。

互斥量

相当于一把锁,我们在访问临界区之前需要加锁,访问完临界资源之后,再把锁解开。

初始化互斥量

1. 静态分配:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER

2. 动态分配:

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t
*restrict attr);
参数:
mutex:要初始化的互斥量
attr:NULL

销毁互斥量

使用静态分配PTHREAD_ MUTEX_ INITIALIZER初始化的互斥量不需要销毁。
不要销毁一个已经加锁的互斥量。
已经销毁的互斥量,要确保后面不会有线程再尝试加锁。

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_mutex_lock时:
互斥量处于未锁状态,该函数会将互斥量锁定,同时返回成功。
发起函数调用时,其他线程已经锁定互斥量,或者存在其他线程同时申请互斥量,但没有竞争到互斥量,那么pthread_ lock调用会陷入阻塞(执行流被挂起),等待互斥量解锁。

条件变量

当一个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了。
如一个线程访问队列时,发现队列为空,它只能等待,只到其它线程将⼀个节点添加到队列中。 这种情况就需要用到条件变量。

 初始化条件变量

int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *rest
rict attr);
参数:
 cond:要初始化的条件变量
 attr:NULL

销毁条件变量

int pthread_cond_destroy(pthread_cond_t *cond);

等待条件变量

int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mute
x);
参数:
 cond:要在这个条件变量上等待
 mutex:互斥量,后⾯详细解释

唤醒等待

int pthread_cond_broadcast(pthread_cond_t *cond);
唤醒所有等待在条件变量上的线程
int pthread_cond_signal(pthread_cond_t *cond);
唤醒第一个等待在条件变量上的线程

条件变量需要使用互斥量
1. 条件等待是线程同步的一种手段,如果只有一个线程,条件不满足,一直等下去都不会满足,所以必须要有一个线程通过某些操作,改变共享变量,使原先不满足的条件变得满足,并且友好的通知等待在条件变量上的线程。
2. 条件不会无缘无故的满足了,必然会牵扯到共享数据的变化,所以一定要用互斥量来保护。没有互斥锁就无法安全的获取和修改共享数据。

假如我们使用pthread_cond_wait即等待条件满足时不加锁,因为等待不是原子操作,那么有可能条件满足,信号发出,但是该信号被错过了,导致线程一直等待,造成死等。所以我们需要对条件变量进行加锁操作。

等待条件代码:

pthread_mutex_lock(&mutex);
while (条件为假)
    pthread_cond_wait(cond, mutex);
修改条件
pthread_mutex_unlock(&mutex);

唤醒条件代码:

pthread_mutex_lock(&mutex);
设置条件为真
pthread_cond_signal(cond);
pthread_mutex_unlock(&mutex);

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值