본문 바로가기
C#

[C#] SpinLock 구현

by 소리쿤 2023. 3. 29.
	class Program
	{
		static SpinLock locked = new SpinLock();
		static int number = 0;

		const int offset = 100000;

		static void Main(string[] args)
		{
			Task t1 = new Task(Thread1);
			Task t2 = new Task(Thread2);

			t1.Start();
			t2.Start();

			Task.WaitAll(t1, t2);

			Console.WriteLine(number);
		}

		static void Thread1()
		{
			for (int i = 0; i < offset; i++)
			{
				locked.Acquire();
				number++;
				locked.Release();
			}
		}

		static void Thread2()
		{
			for (int i = 0; i < offset; i++)
			{
				locked.Acquire();
				number--;
				locked.Release();
			}
		}
	}

	class SpinLock
	{
		volatile int locked = 0;

		public void Acquire()
		{
			while(true)
			{
            			// 여러 스레드가 locked가 0인 것을 체크만 하고 값을 1로 쓰지 않았을 수 있음
				//if(locked == 0)
				//{
				//	locked = 1;
				//}

				int expected = 0; 
				int desired = 1;

				// 기존 locked 값이 expected라면, desired로 바꾼다.
                		// return 값은 기존 locked 값
				if(Interlocked.CompareExchange(ref locked, desired, expected) == expected)
					break;
                    
                Thread.Yield(); // 실행 가능한 스레드에게 현재 컨텍스트 양보
                // Thread.Sleep(0); // 우선 순위가 같거나 높은 스케쥴에게만 양보, 없는 경우 다시 본인 
                // Thread.Sleep(1); // 무조건 1ms 스레드 휴식
			}
		}

		public void Release()
		{
			// 나올 땐 처리할 필요 없음
            		// Interlocked.Exchange(ref locked, 0);
			
			locked = 0;
		}
	}

사용할 수 없다면 while 루프를 계속 도는 lock의 형태

 

문득 c#의 lock의 키워드를 사용하지 않고 이렇게 구현하는 경우가 있을 지가 의문이 들 긴 했다.
while문으로 루프를 돌면, 해당 스레드가 무의미하게 스케쥴링될 거라고 생각했기 때문

 

https://stackoverflow.com/questions/5869825/when-should-one-use-a-spinlock-instead-of-mutex

 

When should one use a spinlock instead of mutex?

I think both are doing the same job,how do you decide which one to use for synchronization?

stackoverflow.com

대충 스레드 Sleep & Awake 및 컨텍스트 스위치 비용이 꽤나 든다는 내용인 걸로 보임

 

크리티컬 섹션의 작업이 적어 락이 빨리 풀릴 것으로 예측된다면, 스레드를 재우지 않는 SpinLock이 쓸만할 듯 하다

 

 

 

'C#' 카테고리의 다른 글

[C#] ReadWriteLock 구현  (0) 2023.04.05
[C#] 공변성, 반공변성  (0) 2023.04.04
[C#] IComparable과 IComparer  (0) 2023.03.26
[C#] Dispose 패턴  (0) 2023.03.23
[C#] Interlocked  (0) 2023.03.20