自旋锁(spinlock):
是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。
什么情况下使用自旋锁:
自旋锁非常有助于避免阻塞,但是如果预期有大量阻塞,由于旋转过多,您可能不应该使用自旋锁。当锁是细粒度的并且数量巨大(例如链接的列表中每个节点一个锁)时以及锁保持时间总是非常短时,旋转可能非常有帮助。
短时间锁定的情况下,自旋锁(spinlock)更快。(因为自旋锁本质上不会让线程休眠,而是一直循环尝试对资源访问,直到可用。所以自旋锁线程被阻塞时,不进行线程上下文切换,而是空转等待。对于多核CPU而言,减少了切换线程上下文的开销,从而提高了性能。)
SpinLock和Lock的区别:
SpinLock,自旋锁。尝试获取该锁的线程持续不断的check是否可以获得。此时线程仍然是激活状态,只是在空转,浪费cpu而已。但是spinlock避免了线程调度和上下文切换,如果锁的时间极短的话,使用该锁反而效率会高。
而lock是线程被block了。这将引起线程调度和上下文切换等行为。
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; namespace spinLock { class Program { //得到当前线程的handler [DllImport("kernel32.dll")] static extern IntPtr GetCurrentThread(); //创建自旋锁 private static SpinLock spin = new SpinLock(); public static void doWork1() { bool lockTaken = false; try { //申请获取锁 spin.Enter(ref lockTaken); //下面为临界区 for(int i=0;i<10;++i) { Console.WriteLine(2); } } finally { //工作完毕,或者发生异常时,检测一下当前线程是否占有锁,如果咱有了锁释放它 //以避免出现死锁的情况 if (lockTaken) spin.Exit(); } } public static void doWork2() { bool lockTaken = false; try { spin.Enter(ref lockTaken); for (int i = 0; i < 10; ++i) { Console.WriteLine(1); } } finally { if (lockTaken) spin.Exit(); } } static void Main(string[] args) { Thread[] t = new Thread[2]; t[0] = new Thread(new ThreadStart(doWork1)); t[1] = new Thread(new ThreadStart(doWork2)); t[0].Start(); t[1].Start(); t[0].Join(); t[1].Join(); Console.ReadKey(); } } }