线程同步主要用于协调对临界资源的访问,临界资源可以是硬件设备(比如打印机)、磁盘(文件)、内存(变量、数组、队列等)。
线程同步有4种机制:
- 临界区
- 互斥量
- 事件
- 信号量
他们的主要区别在于:
- 适用范围:临界区在用户模式下,不会发生用户态到内核态的切换,只能用于同进程内线程间同步。其他会导致用户态到- 内核态的切换,利用内核对象实现,可用于不同进程间的线程同步。
- 性能:临界区性能较好,一般只需数个CPU周期。其他机制性能相对较差,一般需要数十个CPU周期;临界区不支持等待时间,为了获取临界资源,需要不断轮询(死循环或Sleep一段时间后继续查询),其他机制内核负责触发,在对临界资源竞争较少的情况下临界区的性能表现较好,在对临界区资源竞争激烈的情况下临界区有额外的CPU损耗(死循环方式下)或响应时间延迟(Sleep方式下)。
- 应用范围:可用临界区机制实现同进程内的互斥量、事件、信号量功能;互斥量实现了互斥使用临界资源;事件实现单生产多消费(同时只能一个消费)功能;信号量实现多生产多消费功能。
各同步机制详细的功能说明如下:
临界区
临界区是一段独占对某些共享资源访问的代码,在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。
PS:私人浴室(没有管理员)只有一间淋浴房,我想洗澡,我时不时来看下淋浴房空了没,空了我就去洗。
互斥量
功能上跟临界区类似,不过可用于不同进程间的线程同步。
PS:公共浴室(有管理员)只有一间淋浴房,我想洗澡,问了下管理员,有空的淋浴房么,如果有,管理员就让我洗,否则管理员就让我先去休息室睡一觉,等有空的淋浴房了叫醒我去洗澡。
事件
触发重置事件对象,那么等待的所有线程中将只有一个线程能唤醒,并同时自动的将此事件对象设置为无信号的;它能够确保一个线程独占对一个资源的访问。和互斥量的区别在于多了一个前置条件判定。
PS:公共浴室(有管理员)只有一间淋浴房,我想洗澡,问了下管理员,有空的淋浴房么,如果淋浴房没人洗而且打扫完了(等待的事件),管理员就让我洗,否则管理员就让我先去休息室睡一觉,等没人洗而且打扫完了叫醒我去洗澡。
信号量
信号量用于限制对临界资源的访问数量,保证了消费数量不会大于生产数量。
PS:公共浴室(有管理员)有N间(资源数量限制)淋浴房,我想洗澡,问了下管理员,有空的淋浴房么,如果有,管理员就让我洗,否则管理员就让我先去休息室睡一觉,等有空的淋浴房了叫醒我去洗澡。
使用建议
尽量使用用户模式下的临界区机制,避免使用需要用户态到内核态切换的同步机制。