Software Architect/C#

출처 : MSDN - http://msdn.microsoft.com/ko-kr/library/c5kehkcz(v=VS.90).aspx


lock 키워드는 지정된 개체를 상호 배타적으로 잠그고 문을 실행한 다음 잠금을 해제함으로써 문 블록을 임계 영역으로 표시합니다. 이 문은 다음 형식을 사용합니다.

Object thisLock = new Object();
lock (thisLock)
{
    // Critical code section.
}

자세한 내용은 스레드 동기화(C# 프로그래밍 가이드)를 참조하십시오.

lock 키워드를 사용하면 다른 스레드가 코드의 임계 영역에 있는 동안에는 특정 스레드가 임계 영역에 들어갈 수 없습니다. 다른 스레드가 잠긴 코드에 들어가려고 할 경우 개체가 해제될 때까지 대기합니다.

스레딩에 대한 자세한 내용은 스레딩(C# 프로그래밍 가이드) 단원을 참조하십시오.

lock 키워드는 블록의 시작 부분에서 Enter를 호출하고 블록의 끝 부분에서 Exit를 호출합니다.

일반적으로 코드에서 제어되지 않는 인스턴스나 public 형식은 잠그지 않는 것이 좋습니다. 일반적인 구문 lock (this)lock (typeof (MyType)) 및 lock ("myLock")은 다음과 같이 이 지침을 위반합니다.

  • lock (this) - 해당 인스턴스에 공용으로 액세스할 수 있는 경우 문제가 됩니다.

  • lock (typeof (MyType)) - MyType에 공용으로 액세스할 수 있는 경우 문제가 됩니다.

  • lock(¡°myLock¡±) - 동일한 문자열을 사용하는 프로세스의 다른 코드가 동일한 잠금을 공유하게 되므로 문제가 됩니다.

가장 좋은 방법은 private 개체를 정의하여 잠그거나 private static 개체 변수를 정의하여 모든 인스턴스에 공통된 데이터를 보호하는 것입니다.

다음 샘플에서는 C#에서 잠금 없이 스레드를 사용하는 간단한 방법을 보여 줍니다.

//using System.Threading;

class ThreadTest
{
    public void RunMe()
    {
        Console.WriteLine("RunMe called");
    }

    static void Main()
    {
        ThreadTest b = new ThreadTest();
        Thread t = new Thread(b.RunMe);
        t.Start();
    }
}
// Output: RunMe called



다음 샘플에서는 스레드와 lock을 사용합니다. lock 문이 있으면 문 블록이 임계 영역이 되고 balance는 음수가 되지 않습니다.

// using System.Threading;

class Account
{
    private Object thisLock = new Object();
    int balance;

    Random r = new Random();

    public Account(int initial)
    {
        balance = initial;
    }

    int Withdraw(int amount)
    {

        // This condition will never be true unless the lock statement
        // is commented out:
        if (balance < 0)
        {
            throw new Exception("Negative Balance");
        }

        // Comment out the next line to see the effect of leaving out 
        // the lock keyword:
        lock (thisLock)
        {
            if (balance >= amount)
            {
                Console.WriteLine("Balance before Withdrawal :  " + balance);
                Console.WriteLine("Amount to Withdraw        : -" + amount);
                balance = balance - amount;
                Console.WriteLine("Balance after Withdrawal  :  " + balance);
                return amount;
            }
            else
            {
                return 0; // transaction rejected
            }
        }
    }

    public void DoTransactions()
    {
        for (int i = 0; i < 100; i++)
        {
            Withdraw(r.Next(1, 100));
        }
    }
}

class Test
{
    static void Main()
    {
        Thread[] threads = new Thread[10];
        Account acc = new Account(1000);
        for (int i = 0; i < 10; i++)
        {
            Thread t = new Thread(new ThreadStart(acc.DoTransactions));
            threads[i] = t;
        }
        for (int i = 0; i < 10; i++)
        {
            threads[i].Start();
        }
    }
}




신고
1 0