同步,永远是多线程编程中最核心和最重要的话题.同步相关的概念比如:临界区,原子操作,以及互斥量等等
总的来说,在多个线程之间采取同步措施,无非是为了让他们更好的协同工作或者维持共享数据的一致性.
1.共享数据的一致性:
多线程程序多以共享数据作为在线程之间传递数据的手段,由于一个进程所拥有的相当一部分虚拟内存地址都可以被该线程中的所有线程所共享.因此这些被共享的数据大多也已内存空间作为载体.
实际上,保证共享数据一致性的最简单且最好的方法,就是使得该数据成为一个常量,但是如果把一个计数器做成常量是不现实的,一个可以被多个线程访问和改变的计数器只能被看作是一个变量.我要需要通过额外的手段来保证被多个线程共享的变量的一致性.这才有了临界区这个概念.临界区是只能被串行化的访问或执行的某个资源或某段代码.因而临界区也被称作为串行区域.保证临界区有效的最佳方式是利用同步机制,在针对多线程程序的同步机制中包含了很多同步方法,包括原子操作和互斥量,也包括条件变量.
2.互斥量:
在同一时刻,只允许一个线程处于临界区之内的约束被称为互斥(mutex),每一个线程在进入临界区之前都必须先锁定某个对象,只有成功锁定对象的线程才会被允许进入临界区之内,否则会被阻塞,这个对象被称为互斥对象或互斥量.
互斥量有两种状态:已锁定状态和未锁定状态.互斥量每次只能被锁定一次.成功锁定互斥量的线程会成为该互斥量的所有者,只有互斥量的所有者才能对该互斥量进行解锁.
线程在离开互斥量的时候.必须要对响应的互斥量进行解锁.既不能对一个互斥量进行重复锁定,也不能对一个互斥量进行多次解锁.
死锁是使用互斥量的时候需要特别注意的问题.
互斥量简单高效,并适用于绝大部分的共享数据的同步场景.互斥量的实现会使用到机器语言级别的院子操作,并仅在锁定冲突的情况下才会涉及到系统调用的执行.这使得互斥量比其他同步方法(如信号灯)的速度快很多.
3.条件变量:
与互斥量不同,条件变量的作用并不是保证在同一时刻仅有一个线程访问某一个共享数据,而是在对应的共享数据的状态发生变化时,通知其他因此而被阻塞的线程,条件变量总是和互斥量组合使用.互斥量为共享数据的访问提供互斥支持,而条件变量可以就共享数据的状态发生变化向相关线程发出通知,当线程成功锁定互斥量从而访问到共享数据的时候,共享数据的状态并不一定正好满足它的要求.