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 |