Linux 线程间同步

背景知识:

线程 (thread) 线程指代可执行代码的一部分
进程 (process) 指代可执行代码,可以包含多个线程

线程间同步的目的

解决多个线程读写同一个数据时,造成的数据错乱问题

线程间同步的方式

  1. 互斥锁 (Mutex)
  • 目的:保证同一时刻只有一段代码进入临界区进行操作。
  • 做法:
    1. 第一段代码进入临界区之后,执行加锁操作。
    2. 进入临界区之前检查锁变量的bool值,如果为false则会放弃cpu等待进入挂起状态,保存上下文切换部分。
    3. 直到锁的状态发生改变时再唤醒,线程激活进行恢复上下文。
  • 问题:由于存储、恢复上下文会带来一定的开销,不要在性能敏感的地方使用
  1. 自旋锁 (spinlock)
  • 目的:为了节约互斥锁存储恢复上下文的造成的开销。
  • 做法:线程反复检查锁变量是否可用。
while (抢锁(lock)==没抢到) {
}
  • 问题: 会造成忙等待。
  1. 信号量 (Semaphore)
  • 目的:不需要使用忙等待的方法。在信号量只有0或1的时候就是互斥锁。
  • 做法:
    1. 创建一个同步对象作为信号量,该计数值范围为0到最大值。
    2. 线程对信号量等待 (wait) 时,计数值减一;线程对信号量释放 (release) 时,计数值加一。

会出现的问题

  1. 死锁 (deadlock)
  • 出现时机: 两个以上的线程,双方都在等待对方停止运行,以继续运行,但没有一方提前退出。
Linux 线程间同步_第1张图片
死锁示例:P1、P2两个进程都需要有R1、R2两个资源才能继续运行。P1拥有R2,需要R1才能继续运行;P2拥有R1,需要R2才能继续运行。都在互相等待,导致死锁。
  1. 数据竞争 (race hazard)
  • 出现时机:两个进程同时修改一个共享内容,没有并发控制的情况下,最后结果依赖于进程的执行顺序。并有可能会发生并发访问冲突。

参考文章

互斥锁,同步锁,临界区,互斥量,信号量,自旋锁之间联系是什么?
信号量wiki
死锁wiki
数据竞争wiki

你可能感兴趣的:(Linux 线程间同步)