自旋锁与相互排斥锁之抉择

自旋锁和相互排斥锁是多线程编程中的两个重要概念。他们都能用来锁定一些共享资源,以阻止影响数据一致性的并发訪问。可是他们之间确实存在差别,那么这些差别是什么?

1    理论

理论上,当一个线程试图获取一个被锁定的相互排斥锁时,该操作会失败然后该线程会进入睡眠,这样就能立即让还有一个线程执行。当持有相互排斥锁的线程释放该锁之后,进入睡眠状态的线程就会被唤醒。可是,当一个线程试图获取一个自旋锁而没有成功时,该线程会不断地重试,直到终于成功为止;因此该线程不会将执行权交到其它线程手中(当然,一旦当前线程的时间片超时,操作系统会强行切换到还有一个线程)。

2    问题

相互排斥锁的问题在于:让线程睡眠和唤醒线程都是极为耗时的操作,完毕这些操作须要大量CPU指令,因此也就须要耗费不少时间。假设仅仅是锁定相互排斥锁非常短一段时间,那么让线程睡眠和唤醒线程所花的时间可能会超过线程实际上睡眠的时间,甚至有可能会超过线程在自旋锁上轮询锁浪费的时间(假设使用自旋锁)。还有一方面,在自旋锁上进行轮询会浪费CPU时间,假设自旋锁被锁定较长的时间,可能会浪费大量的CPU时间,这时让线程睡眠可能是一个更好的选择。

3    解决方法

在一个单核系统中使用自旋锁是行不通的,由于只要自旋锁轮询在堵塞当前CPU,那么就没有其它线程可以执行,既然没有其它线程可以执行,那么该锁也就不会被唤醒,对,我们进入死锁了。最好情况下,自旋锁只浪费那些对系统没有不论什么用处的CPU时间。相反,假设使用相互排斥锁,线程A进入睡眠,那么另外一个线程B就行马上执行,线程B有可能会释放锁,唤醒线程A,使线程A继续执行。

在一个多核系统,假设大量的锁仅仅持有非常短一段时间,那么让线程睡眠和唤醒线程所浪费的时间有可能会极大地减少执行时性能。相反,假设使用自旋锁,线程就有机会利用全然时间片(总是堵塞非常短一段时间,然后马上执行),获得更高的吞吐量。

4    实践

由于大部分情况下,程序猿不能预先知道使用相互排斥锁好还是使用自旋锁好(比如:由于不知道目标系统的CPU核心数量),同一时候操作系统也不知道某个片段的代码是否已经为单核或多核环境优化过,因此大部分系统不严格区分这两种锁。实际上,大部分现代操作系统都提供混合相互排斥锁和混合自旋锁。那么,什么是混合相互排斥锁和混合自旋锁?

在一个多核系统,混合相互排斥锁開始时会表现得像自旋锁。即假设一个线程A不能获取到相互排斥锁,那么线程A不会立即进入睡眠状态,由于该锁可能立即就被释放了,因此该相互排斥锁開始表现得像自旋锁。仅仅有当一段固定的时间后,线程A还不能获取到该相互排斥锁,线程A才会进入睡眠状态。假设同样的程序执行在单核系统下,该相互排斥锁就不会表现出自旋锁的行为。

一个混合自旋锁開始时会表现得像一个普通的自旋锁,但为了避免浪费CPU时间,它提供了一个back-off策略。通常,混合自旋锁不会使线程进入睡眠状态(由于当你使用自旋锁时,你不希望发生这样的情况),可是它能停止某个线程(马上或者一段固定的时间后),然后让还有一个线程执行,以提高自旋锁的闲置率(一个纯粹的线程切换通常比使线程进入睡眠然后唤醒它效率更高,起码眼下如此)。

5    总结

假设你不知道该使用哪一个,那么使用相互排斥锁,由于大部分现代操作系统都同意他们先自旋一小段时间(提前是该自旋故意), 所以相互排斥锁一般是更好的选择。有时,使用自旋锁会提升性能,在某些特定情况下,你可能会认为使用自旋锁更好。这时候,使用你自己的锁对象,该锁对象内部使用自旋锁或者相互排斥锁实现(这个行为能够通过配置改动),開始时所有使用相互排斥锁,之后,假设你认为某个地方使用自旋锁更好,那么改动它,然后比較下结果,可是在下结论之前,一定要记得在单核和多核环境下进行測试。

自旋锁与相互排斥锁之抉择

时间: 2024-10-01 00:38:24

自旋锁与相互排斥锁之抉择的相关文章

Linux 同步方法剖析--内核原子,自旋锁和相互排斥锁

在学习 Linux® 的过程中,您或许接触过并发(concurrency).临界段(critical section)和锁定,可是怎样在内核中使用这些概念呢?本文讨论了 2.6 版内核中可用的锁定机制,包含原子运算符(atomic operator).自旋锁(spinlock).读/写锁(reader/writer lock)和内核信号量(kernel semaphore). 本文还探讨了每种机制最适合应用到哪些地方.以构建安全高效的内核代码. 本文讨论了 Linux 内核中可用的大量同步或锁定

线程同步与相互排斥:相互排斥锁

为什么须要相互排斥锁? 在多任务操作系统中,同一时候执行的多个任务可能都须要使用同一种资源.这个过程有点类似于,公司部门里.我在使用着打印机打印东西的同一时候(还没有打印完).别人刚好也在此刻使用打印机打印东西,假设不做不论什么处理的话,打印出来的东西肯定是错乱的. 以下我们用程序模拟一下这个过程.线程一须要打印" hello ",线程二须要打印" world ",不加不论什么处理的话.打印出来的内容会错乱: [cpp] view plaincopy #includ

RAII手法封装相互排斥锁

CriticalSectionWrapper是一个接口类 class CriticalSectionWrapper { public: // Factory method, constructor disabled static CriticalSectionWrapper* CreateCriticalSection(); virtual ~CriticalSectionWrapper() {} // Tries to grab lock, beginning of a critical se

深入理解相互排斥锁的实现

在实际的软件编程中,常常会遇到资源的争用,比方以下的样例: [cpp] view plaincopyprint? class Counter { private: int value; public: Counter(int c) { value = c; } int GetAndIncrement() { int temp = value; //进入危急区 value = temp +1; //离开危急区 return value; } } class Counter { private: i

Linux多线程同步之相互排斥量和条件变量

1. 什么是相互排斥量 相互排斥量从本质上说是一把锁,在訪问共享资源前对相互排斥量进行加锁,在訪问完毕后释放相互排斥量上的锁. 对相互排斥量进行加锁以后,不论什么其它试图再次对相互排斥量加锁的线程将会被堵塞直到当前线程释放该相互排斥锁.假设释放相互排斥锁时有多个线程堵塞,所以在该相互排斥锁上的堵塞线程都会变成可进行状态.第一个变成执行状态的线程能够对相互排斥量加锁.其它线程在次被堵塞,等待下次执行状态. pthread_mutex_t 就是POSIX对于mutex的实现. 函数名 參数 说明 p

Linux同步与相互排斥应用(零):基础概念

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途] 当操作系统进入多道批处理系统时代以后.一个系统中就存在多个任务,每一个任务都依照一定的算法进行调度来使用内存.cpu等共享资源. 当当中一个任务等待其它资源时,该任务能够临时睡眠,操作系统调度另外任务继续运行额,这样能够使系统资源得到最大化利用.而无需像曾经单道批处理系统那样仅仅有当一个任务完毕之后才运行下一个任务. 可是由此也引入了多任务并发

虚拟机中的锁优化简介(适应性自旋/锁粗化/锁削除/轻量级锁/偏向锁)

高效并发是JDK 1.6的一个重要主题,HotSpot虚拟机开发团队在这个版本上花费了大量的精力去实现各种锁优化技术,如适应性自旋(Adaptive Spinning).锁削除(Lock Elimination).锁膨胀(Lock Coarsening).轻量级锁(Lightweight Locking).偏向锁(Biased Locking)等,这些技术都是为了在线程之间更高效地共享数据,以及解决竞争问题,从而提高程序的执行效率. 13.3.1 自旋锁与自适应自旋 前面我们讨论互斥同步的时候,

JVM中锁优化,偏向锁、自旋锁、锁消除、锁膨胀

详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt364 本文将简单介绍HotSpot虚拟机中用到的锁优化技术. 自旋锁 互斥同步对性能最大的影响是阻塞的实现,挂起线程和恢复线程的操作都需要转入内核态中完成,这些操作给系统的并发性能带来了很大的压力.而在很多应用上,共享数据的锁定状态只会持续很短的一段时间.若实体机上有多个处理器,能让两个以上的线程同时并行执行,我们就可以让后面请求锁的那个线程原地自旋(不放弃CPU时间),看

Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等(转)

Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁 / 非公平锁 可重入锁 / 不可重入锁 独享锁 / 共享锁 互斥锁 / 读写锁 乐观锁 / 悲观锁 分段锁 偏向锁 / 轻量级锁 / 重量级锁 自旋锁 上面是很多锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计,下面总结的内容是对每个锁的名词进行一定的解释. 公平锁 / 非公平锁 公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁. 非公