2016-09-26 4 views
1

멀티 스레딩을 처음 사용하는 데 문제가 있습니다. 나는 그것이 어떻게 작동하는지 이해하기를 원한다. 그래서 나는 그것을 썼다.C에서 멀티 스레딩 문제를 파악할 수 없습니다.

internal abstract class PaySystem 
{ 
    public int payOperationTime; 
    public readonly object _payLock = new object(); 

    public void Pay() 
    { 
     Console.WriteLine("There is a pay order in {0} pay system", GetType().Name); 

     if (Monitor.TryEnter(_payLock)) 
     { 
      Console.WriteLine("{0} pay system is ready work, so we can start pay operation", GetType().Name); 
     } 
     else 
     { 
      Console.WriteLine("{0} pay system is locked now by other pay operation, so we need to wait for end of last", GetType().Name); 
     } 

     lock (_payLock) 
     { 
      Console.WriteLine("Start pay operation on {0} pay sytem", GetType().Name); 
      Console.WriteLine("payOperationTime for {0} paySystem will be {1}", GetType().Name, payOperationTime.ToString()); 
      Thread.Sleep(payOperationTime); 
     } 

     Console.WriteLine("Pay done by {0} pay system", GetType().Name); 

    } 
} 

그래서, 내 홈페이지에() 메소드는 다음에 일어날 :

그래서, 클래스 PaySystem이

 PayPal payPal = new PayPal(); 

     Thread payPalPayment = new Thread(payPal.Pay); 
     Thread payPalPayment2 = new Thread(payPal.Pay); 

     payPalPayment.Start(); 
     payPalPayment2.Start(); 

     Console.ReadKey(true); 

그리고 출력으로 나는 결과 (내게로) 예측할 수있다. 콘솔 출력의 printscreen을 파일로 첨부합니다.

enter image description here

는하지만, 몇 마디에, 그것은 첫 번째 스레드가 종료 한 후 두 번째 스레드가 지불을 계속할 것 같습니다.

제대로 이해하면 스레드를 시작할 수 있으며 사물함 잠금이 해제 될 때 사물함에 의해 잠겨져 실행되거나 도달되는 것을 차단할 수 있습니다.

내가 이해하지 못하거나 올바르게하지 않은 것을 설명 할 수 있습니까?

EDIT 1 개

내 질문은 왜 두 번째 스레드가없는 것입니다 contines 지불합니까? 잠긴 코드 블록의 행.

편집 2. 대답

내가 사물함 개체가 잠겨 있는지 확인하고 싶어, 내가 TryEnter() 메소드를 사용했다. 내가 도움이, 친애하는 stackoverflow 청중, 내 목적을 위해 IsEntered() 메서드를 사용해야합니다 알아낼.

감사합니다.

+1

먼저 문제를 제대로 설명해 줄 수 있습니까? 그것을 얻는데 어려움을 겪고 있습니다. – Rahul

+1

'PayPal'은 어디에 정의되어 있습니까? –

+1

코드가 기대하는 바가 내게 명확하지 않습니다. 첫 번째 스레드는 먼저 잠금을 가졌으므로 잠금 내에서 작업을 수행했습니다. 두 번째 스레드가 잠겨있을 때까지 첫 번째 스레드는 이미 그것을 가지고 있습니다. – David

답변

0

개체가 잠겨 있는지 확인하려면 Monitor.IsEntered() 메서드를 사용해야합니다.

1

잠금을 두 번 획득하고 잠금을 한 번만 풀면 잠금이 유지됩니다. TryEnter에 대한 호출이 성공하면 획득 한 잠금이 해제되지 않으므로 다른 스레드가 진행을 방해하지 않습니다.

+1

'TryEnter'는'IsEntered'로 대체되어야합니다. 편집 : Vladislav Hromyh 원래 유료() 함수. – SuperOli

+0

payLock이 읽기 전용으로 정의 된 이유는 무엇입니까? – MrSykkox

+1

@ MrSykkox 왜 '읽기 전용'이되어서는 안되나요? 잠금 객체를 변경해야 할 이유가 없으므로 '읽기 전용'으로 설정하면 잠금 객체를 적용하지 않는 것이 합리적입니다. – Kyle

3

Monitor.Enter 및 lock과 혼동스러워 보입니다.

Monitor.TryEnter는 개체에 대한 잠금을 얻으려고합니다. 성공하면 개체를 Monitor.Exit 할 때까지 잠긴 상태로 유지됩니다. 당신은 절대로하지 않습니다.

잠금은 Monitor.Enter와 Monitor.Exit (블록 끝 부분)의 줄임말입니다. 자물쇠가 필요합니다. Monitor.TryEnter를 꺼내면 예상대로 작동합니다.

+0

Nikki이 정확합니다. lock {}은 스레드 동기화와 관련하여 간단한 설명이 필요할 때 유용합니다. 그러나 동시 작업을 "건너 뛸"수있는 스레드가 필요한 경우 (TryEnter를 시간 초과와 함께 실행하여) Monitor.TryEnter() 메서드를 사용하면 장시간 차단을 피할 수 있습니다. – Michael

0

Monitor.TryEnter + Monitor.Exit 또는 단지 Lock을 사용하십시오.

Lock 문은 리소스를 잠 그어 해제합니다. Monitor.TryEnter은 잠금 만합니다.