スピンロック

6559 ワード

スピンロック:
つまり、あるスレッドがロックを取得している間に、ロックが他のスレッドによって取得された場合、そのスレッドはループを待機し、ロックが正常に取得されるかどうかを絶えず判断し、ロックが取得されるまでループを終了しないことを意味する.
 
スピンロックを使用する場合:
スピンロックはブロックを回避するのに非常に役立ちますが、大量のブロックが予想される場合は、回転が多すぎるため、スピンロックを使用するべきではない場合があります.ロックが細粒度であり、リンクされたリスト内のノードごとに1つのロックなどの数が大きい場合、ロック保持時間が常に非常に短い場合、回転が非常に役立つ可能性があります.
短時間ロックの場合、スピンロック(spinlock)の方が高速です.(スピンロックは本質的にスレッドをスリープさせることなく、利用可能になるまでリソースへのアクセスを繰り返しています.そのため、スピンロックスレッドがブロックされている場合は、スレッドコンテキストの切り替えを行わずにアイドリング待機します.マルチコアCPUでは、スレッドコンテキストの切り替えにかかるオーバーヘッドが低減され、パフォーマンスが向上します.)
 
SpinLockとLockの違い:SpinLock,スピンロック.ロックを取得しようとするスレッドが継続的にcheckを取得できるかどうか.このときスレッドはまだアクティブな状態であり,空転し,cpuを浪費しているだけである.しかしspinlockはスレッドスケジューリングとコンテキスト切替を回避し,ロックの時間が極めて短いと,このロックを使用するとかえって効率が高くなる.ロックはスレッドが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();
        }
    }
}