Fork me on GitHub

自旋锁-SpinLock(.NET 4.0+)

短时间锁定的情况下,自旋锁spinlock更快。(因为自旋锁本质上不会让线程休眠,而是一直循环尝试对资源访问,直到可用。所以自旋锁线程被阻塞时,不进行线程上下文切换,而是空转等待。对于多核CPU而言,减少了切换线程上下文的开销,从而提高了性能

以下是简单实例(并行执行10000次,每次想list中添加一项。执行完后准确的结果应该是10000):

foo1:使用系统的自旋锁。

foo4:不使用锁。结果必然是不正确的。

foo5:通过Interlocked实现自旋锁。

  1    public class SpinLockDemo
  2     {
  3         int i = 0;
  4         List<int> li = new List<int>();
  5         SpinLock sl = new SpinLock();
  6         int signal = 0;
  7 
  8         public void Execute() 
  9         {
 10             foo1();
 11             //li.ForEach((t) => { Console.WriteLine(t); });
 12             Console.WriteLine("Li Count - Spinlock: "+li.Count);
 13             li.Clear();
 14             foo4();
 15             Console.WriteLine("Li Count - Nolock: " + li.Count);
 16             li.Clear();
 17             foo5();
 18             Console.WriteLine("Li Count - Customized Spinlock: " + li.Count);
 19 
 20         }
 21 
 22         public void foo1()
 23         {
 24             Parallel.For(0, 10000, r =>
 25             {
 26                 bool gotLock = false;     //释放成功
 27                 try
 28                 {
 29                     sl.Enter(ref gotLock);    //进入锁
 30                     //Thread.Sleep(100);
 31                     if (i == 0)
 32                     {
 33                         i = 1;
 34                         li.Add(r);
 35                         i = 0;
 36                     }
 37                 }
 38                 finally
 39                 {
 40                     if (gotLock) sl.Exit();  //释放
 41                 }
 42 
 43             });
 44         }
 45 
 46         public void foo4()
 47         {
 48             Parallel.For(0, 10000, r =>
 49             {
 50                 if (i == 0)
 51                 {
 52                     i = 1;
 53                     li.Add(r);
 54                     i = 0;
 55                 }
 56             });
 57         }
 58 
 59         public void foo5()
 60         {
 61             Parallel.For(0, 10000, r =>
 62             {
 63                 while (Interlocked.Exchange(ref signal, 1) != 0)//加自旋锁
 64                 {}
 65                 li.Add(r);
 66                 Interlocked.Exchange(ref signal, 0);  //释放锁
 67             });
 68 
 69         }
 70 
 71         public void foo6()
 72         {
 73             //Console.WriteLine(i);
 74             //Task.Run(new Action(foo2)).ContinueWith(new Action<Task>(t =>
 75             //{
 76             //    Console.WriteLine("foo2 completed: " + i);
 77             //}));
 78             //Console.WriteLine(i);
 79             //Task.Run(new Action(foo2)).ContinueWith(new Action<Task>(t =>
 80             //{
 81             //    Console.WriteLine("foo3 completed: " + i);
 82             //}));
 83             //Console.WriteLine(i);
 84         }
 85         public void foo2()
 86         {
 87             bool lck = false;
 88             sl.Enter(ref lck);
 89             Thread.Sleep(100);
 90             ++i;
 91             if (lck) sl.Exit(); 
 92         }
 93 
 94         public void foo3()
 95         {
 96             bool lck = false;
 97             sl.Enter(ref lck);
 98             ++i;
 99             if (lck) sl.Exit();
100         }
101     }

 

结果如下:

 

posted @ 2016-03-12 19:04  ZHK的博客  阅读(2396)  评论(0编辑  收藏  举报