본문 바로가기
컴퓨터/C#

[C#] lock 블럭

by Luyin 2013. 6. 2.

출처 : http://csharpstudy.com/Threads/lock.aspx

아래 예제는 여러 개의 스레드가 Thread-Safe 하지 않은 메서드를 호출하는 예를 보여주고 있다. 10개의 스레드가 counter라는 필드를 동시에 쓰거나 읽는 샘프롤서 한 스레드가 counter변수를 변경하고 읽기 전에 다른 스레드가 다시 counter변수를 변경할 수 있기 때문에 불확실한 결과를 출력하게 된다.


예제

using System;
using System.Threading;

namespace MultiThrdApp
{
    class MyClass
    {
        private int counter = 1000;

        public void Run()
        {
            // 10개의 쓰레드가 동일 메서드 실행
            for (int i = 0; i < 10; i++)
            {
                new Thread(UnsafeCalc).Start();    
            }
        }

        // Thread-Safe하지 않은 메서드 
        private void UnsafeCalc()
        {
            // 객체 필드를 모든 쓰레드가 
            // 자유롭게 변경
            counter++;

            // 가정 : 다른 복잡한 일을 한다
            for (int i = 0; i < counter; i++)
                for (int j = 0; j < counter; j++) ;

            // 필드값 읽기
            Console.WriteLine(counter);
        }
    }
}



C# lock 키워드

C#의 lock 키워드는 특정 블럭의 코드(Critical Section이라 부른다)를 한번에 하나의 스레드만 실행할 수 있도록 해준다. lock()의 파라미터에는 임의의 객체를 사용할 수 있는데, 주로 object타입의 private 필드를 지정한다. lock(this)와 같이 클래스 객체 전체를 지정하는 this를 사용할 수도 있는데, 이는 불필요하게 모든 클래스 객체를 잠그는 효과가 있으므로, object타입의 필드를 만들어 사용하는 것이 좋다. Critical Section 코드 블록은 가능한 한 범위를 작게하는 것이 좋은데, 이는 필요한 부분만 Locking한다는 원칙에 따른 것이다.


예제

using System;
using System.Threading;

namespace MultiThrdApp
{
    class MyClass
    {
        private int counter = 1000;

        // lock문에 사용될 객체
        private object lockObject = new object();

        public void Run()
        {
            // 10개의 쓰레드가 동일 메서드 실행
            for (int i = 0; i < 10; i++)
            {
                new Thread(SafeCalc).Start();    
            }
        }

        // Thread-Safe 메서드 
        private void SafeCalc()
        {
            // 한번에 한 쓰레드만 lock블럭 실행
            lock (lockObject)
            {
                // 필드값 변경
                counter++;

                // 가정 : 다른 복잡한 일을 한다
                for (int i = 0; i < counter; i++)
                    for (int j = 0; j < counter; j++) ;

                // 필드값 읽기
                Console.WriteLine(counter);
            }
        }

        //출력 예:
        // 1001
        // 1002
        // 1003
        // 1004
        // 1005
        // 1006
        // 1007
        // 1008
        // 1009
        // 1010
    }
}


'컴퓨터 > C#' 카테고리의 다른 글

C#에서 C++ DLL 사용하기  (1) 2013.06.29
[.NET] CLR(Common Language Runtime, 공통 언어 실행 환경)  (0) 2013.06.07
[C#] 객체와 생성  (0) 2013.05.28
[C#] get, set 함수  (0) 2013.01.18
[C#] TCP, UDP MultiThread Client Source Code  (0) 2013.01.07