Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
05-17 00:00
관리 메뉴

nomad-programmer

[Programming/C#] Monitor 클래스로 동기화 : Enter() & Exit() 본문

Programming/C#

[Programming/C#] Monitor 클래스로 동기화 : Enter() & Exit()

scii 2020. 9. 29. 16:41

Monitor 클래스는 스레드 동기화에 사용하는 몇 가지 정적 메소드를 제공한다. Monitor.Enter()와 Monitor.Exit() 메소드다. 이 두 메소드는 lock 키워드와 완전히 똑같은 기능을 한다.

  • Monitor.Enter() 메소드는 크리티컬 섹션을 만든다.
  • Monitor.Exit() 메소드는 크리티컬 섹션을 제거한다.

Monitor.Enter() 메소드는 lock 블록의 { (여는 괄호), Monitor.Exit() 메소드는 lock 블록의 } (닫는 괄호) 에 해당한다고 할 수 있다.

// lock 키워드

public void Increase()
{
    int loopCount = 1000;
    while (loopCount-- > 0)
    {
        lock (thisLock)
        {
            count++;
        }
    }
}
// Monitor 클래스

public void Increase()
{
    int loopCount = 1000;
    while (loopCount-- > 0)
    {
        Monitor.Enter(thisLock);
        try
        {
            count++;
        }
        finally
        {
            Monitor.Exit(thisLock);
        }
    }
}

lock 키워드는 Monitor 클래스의 Enter() 메소드와 Exit() 메소드를 바탕으로 구현된 키워드다. 그러니 Monitor.Enter()와 Monitor.Exit() 메소드로 동기화를 할 것 같으면 차라리 간편하게 lock 키워드를 사용하는 편이 낫다. 코드도 읽기가 좋고 잘못 사용한 Monitor.Exit() 메소드 때문에 프로그램에 버그가 생길 가능성도 없기 때문이다.

Monitor 클래스를 이용한 멀티 스레드 동기화 예제

using System;
using System.Threading;

namespace CSharpExample
{
    class Counter
    {
        const int LOOP_COUNT = 1000;
        readonly object thisLock;

        public int Count { get; set; }

        public Counter()
        {
            thisLock = new object();
            Count = 0;
        }

        public void Increase()
        {
            int loopCount = LOOP_COUNT;
            while (loopCount-- > 0)
            {
                Monitor.Enter(thisLock);
                try
                {
                    Count++;
                }
                finally
                {
                    Monitor.Exit(thisLock);
                }
                Thread.Sleep(1);
            }
        }

        public void Decrease()
        {
            int loopCount = LOOP_COUNT;
            while (loopCount-- > 0)
            {
                Monitor.Enter(thisLock);
                try
                {
                    Count--;
                }
                finally
                {
                    Monitor.Exit(thisLock);
                }
                Thread.Sleep(1);
            }
        }

    }
    internal class MainApp
    {
        static int Main(string[] args)
        {
            Counter counter = new Counter();

            Thread incThread = new Thread(new ThreadStart(counter.Increase));
            Thread decThread = new Thread(new ThreadStart(counter.Decrease));

            incThread.Start();
            decThread.Start();

            incThread.Join();
            decThread.Join();

            Console.WriteLine(counter.Count);

            return 0;
        }
    }
}


/* 결과

0

*/
Comments