互斥锁,读写锁,条件变量,自旋锁

互斥锁

在多线程的情况下,当一个变量可以被多个线程修改时,就需要考虑多线程同步问题。线程A修改变量前,先加锁,修改结束再解锁,然后线程B获取同样的锁,修改结束再解锁,如果不是同一把锁,同步是无效的。

在C++中使用pthread的互斥量接口实现数据同步,线程A对互斥量mutex加锁后,其他尝试加锁的线程都会阻塞,等线程A解锁后,其他线程从阻塞变为运行态,第一个抢到CPU的线程加锁成功,其他线程再次阻塞,这样每次只有一个线程能加锁。这里存在规则统一的问题,就是线程可以在不加锁情况下访问变量,此时即使另一个线程加了锁,还是会出现不同步的问题,所以不能有的线程需要加锁,有的线程不需要加锁,必须统一化。

死锁

存在两种常见的死锁情况,第一种是对同一把锁连续加锁,结果第二次加锁时因为自己已经加了锁,会导致线程阻塞无法运行。
互斥锁,读写锁,条件变量,自旋锁_第1张图片

第二种是两个线程各自加了一把锁之后,还未解锁就去获取对方的锁。
互斥锁,读写锁,条件变量,自旋锁_第2张图片
线程t1加了锁A,t2加了锁B,两个线程都未解锁,然后t1去获取锁B,此时t1会阻塞;同样t2去获取锁A,也会阻塞。两个线程都阻塞也就无法解锁,程序无法再运行。此时可以将两个线程都杀死。为防止这种情况可以用trylock函数。
互斥锁,读写锁,条件变量,自旋锁_第3张图片

读写锁

读写锁是一种较一般化的互斥锁,主要用于读操作比较多、写操作少的多线程情况。读写锁有三种状态:读锁、写锁、不锁。遵循写互斥,读共享,写优先的原则。

常见的有下面几种情况:
1. 多个线程可以同时占有读锁
2. 每次只能有一个写线程,一个线程加了写锁,其他线程无论读写都要等待,解锁后,优先唤醒占有写锁的线程
3. 一个线程加读锁,此时来了一个占写锁的线程和一个读锁的线程,则二者皆阻塞,解锁后,写锁的线程优先。

读写锁在使用前要初始化,释放底层内存前要销毁。

你可能感兴趣的:(Linux)