[Thread] 동기화 / 임계 영역 ( Interlocked, Lock, Moniter )
🚀 동기화의 개념
멀티 스레드 환경에서는 여러개의 스레드가 하나의 공유 데이터를 사용하기에 하나의 스레드에서 데이터를 저장하는 동안 다른 스레드에서 데이터를 읽거나 그 반대의 경우처럼 여러가지 문제가 생길 수 있다. 따라서 데이터를 저장하는 동안에는 데이터를 읽지 못하게 해야하고, 데이터를 읽는 동안에는 데이터를 쓰지 못하도록 해야한다. 이 때 필요한 개념은 한 쓰레드가 작업 중 다른 쓰레드에 의해 간섭을 받지 못하도록 막는 쓰레드의 동기화이다.
동기화는 임계 영역에서 스레드들이 순서를 갖춰 자원을 사용한다.
🚀 동기화 방법
🔥 Interlocked
-
C#의 Interlocked는 다중 스레드에서 공유하는 변수에 대해 원자 단위 연산을 제공한다.
-
임계 구역내의 고유 자원의 변수에 대한 원자성을 보장한다는 것이다
여기서의 원자성이란 모두 실행되던지, 모두 실행되지 않도록 하던지를 보장하는 특성이다.
static int num = 0;
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(num);
}
static void Thread1()
{
for(int i = 0; i< 1000000; i ++)
{
num++;
}
}
static void Thread2()
{
for (int i = 0; i < 1000000; i++)
{
num--;
}
}
C#의 Interlocked는 다중 스레드에서 공유하는 변수에 대해 원자 단위 연산을 제공한다.
임계 구역내의 고유 자원의 변수에 대한 원자성을 보장한다는 것이다
여기서의 원자성이란 모두 실행되던지, 모두 실행되지 않도록 하던지를 보장하는 특성이다.
static int num = 0;
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(num);
}
static void Thread1()
{
for(int i = 0; i< 1000000; i ++)
{
num++;
}
}
static void Thread2()
{
for (int i = 0; i < 1000000; i++)
{
num--;
}
}
위의 코드에서는 공유 자원인 num을 두 개의 스레드가 접근한다. 첫번째 스레드는 백만번 1을 증가시키고 두번째 스레드는 백만번 1을 감소시키기에 두 스레드가 끝날 시 num의 값은 0이 될 것으로 예상할 수 있지만,
실제로는 엉뚱한 값이 출력되게 된다. 그 이유는 두 개의 스레드가 병렬적으로 진행되기에 자원의 원자성을 보장받지 못하기 때문이다. 따라서 공유 자원인 num에 interlocked를 이용해 원자성을 보장해주어야 한다.
static int num = 0;
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(num);
}
static void Thread1()
{
for(int i = 0; i< 1000000; i ++)
{
Interlocked.Increment(ref num);
}
}
static void Thread2()
{
for (int i = 0; i < 1000000; i++)
{
Interlocked.Decrement(ref num);
}
}
위의 코드 처럼 Interlocked 클래스의 Increment와 Decrement를 통해 원자성을 보장해주었다.
이 때의 실행결과는 예상했던 값과 그대로 0이 출력되는 것을 볼 수 있다.
🔥 Lock
- 상호 배제 잠금을 획득하여, 블럭 실행 후 잠금을 해제한다.
- 다른 스레드에서는 잠금 획득이 차단되고, 잠금이 해제될 때 까지 대기 한다
class Program
{
static int Count = 0;
static System.Object lockThis = new System.Object();
static void Print()
{
lock (lockThis)
{
for(int i =0; i< 5; i++)
{
Count++;
Console.WriteLine(Count);
}
}
}
static void Main(string[] args)
{
Thread thread1 = new Thread(new ThreadStart(Print));
Thread thread2 = new Thread(new ThreadStart(Print));
Thread thread3 = new Thread(new ThreadStart(Print));
Thread thread4 = new Thread(new ThreadStart(Print));
thread1.Start();
thread2.Start();
thread3.Start();
thread4.Start();
}
}
- 하나의 스레드에서 잠금이 풀릴 때 까지 다른 스레드에서는 대기하고 있다가 잠금이 풀리면 실행되는 것을 볼 수 있다
🔥 Moniter
- Moniter 또한 lock과 마찬가지로 코드 블록이 여러 스레드에서 동시에 실행되지 않도록 방지한다
class Program
{
static int Count = 0;
static System.Object moniterlock = new System.Object();
static void Print()
{
Monitor.Enter(moniterlock);
try
{
for(int i = 0; i<5; i++)
{
Count++;
Console.WriteLine(Count);
}
}
finally
{
Monitor.Exit(moniterlock);
}
}
static void Main(string[] args)
{
Thread thread1 = new Thread(new ThreadStart(Print));
Thread thread2 = new Thread(new ThreadStart(Print));
Thread thread3 = new Thread(new ThreadStart(Print));
Thread thread4 = new Thread(new ThreadStart(Print));
thread1.Start();
thread2.Start();
thread3.Start();
thread4.Start();
}
}
Ref https://www.hanbit.co.kr/network/category/category_view.html?cms_code=CMS1669525805
https://neohtux.tistory.com/220?category=620074
https://scvtwo.tistory.com/67
Author And Source
이 문제에 관하여([Thread] 동기화 / 임계 영역 ( Interlocked, Lock, Moniter )), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@uchang903/Thread-동기화-임계-영역-Interlocked-Lock-Moniter저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)