2009-10-23 5 views
10

내 멀티 스레딩 응용 프로그램에서 같은 시간에 많은 인스턴스에서 변경할 수있는 일부 변수를 사용하고 있습니다. 그것은 이상하지만 그것은 아무 문제없이 잘 작동했다.하지만 물론 스레드로부터 안전하게 만들 필요가있다. 나는 자물쇠로 막 시작 했으므로 충고를 부탁한다.속성의 잠금, 좋은 접근법?

클라이언트가 연결되면 각 클라이언트가 자신의 "A"변수를 갖는 클래스 클라이언트가 생성된다. 5 개 클래스가 동시에 (스레드)에서 수행 한 경우에도 지금과까지

Client selectedClient SelectOtherClientClassByID(sentID); 

selectedClient.A=5; 

문제 없음, 그러나 나는 특성에 잠금 장치를 추가하는 방법에 대해 무엇을 생각했다 :

때때로, 클라이언트 메소드처럼 호출하지 ?

처럼 :

A { 
    get { return mA; } 
    set { 
     // use lock here for settting A to some value 
    }  
} 

이 괜찮을까요?

답변

16

두 세트 모두 잠금을 사용해야합니다. 이 잠금은 동일한 객체 여야합니다. 예를 들면 다음과 같습니다.

private object mylock = new object(); 

public int A { 

    get { 
    int result; 
    lock(mylock) { 
    result = mA; 
    } 
    return result; 
    } 

    set { 
    lock(mylock) { 
     mA = value; 
    } 
    } 
} 
+1

감사합니다 ... btw for reading 다른 클래스의 독서 중 변경 될 수 있기 때문에? – Petr

+1

외부에서 액세스 할 수 있으므로이 설정을 잠그는 것은 좋지 않습니다. –

+0

설정하는 동안 변경 될 수 있습니다. 잠금 장치는 장벽 역할을하여 잠금 장치 소유자가 잠금 장치를 해제 할 때까지 다른 동작을 방지합니다. –

2

필요한 모든 것이 단일 속성으로 설정되는 경우 매우 드뭅니다. 더 자주 selectedClient.A = 5은 훨씬 더 큰 논리적 작업의 일부가 될 것이며, 여기에는 몇 가지 할당/평가/등이 포함됩니다. 이 전체 작업을 수행하는 동안 selectedClient을 일관된 상태로 유지하고 교착 상태/경쟁 조건을 도입하지 않는 것이 좋습니다. 접근의 내부 속성에 액세스 잠금

Client selectedClient = GetClient(...); 

lock(selectedClient.SyncRoot) 
{ 
    selectedClient.A = 5; 
    selectedClient.B = selectedClient.A * 54; 
} 
+0

하나의리스트와 int를 공유하는 다른 변수는 없습니다. 주로 SyncRoot에 대해서는 아직 알지 못합니다. – Petr

+0

SyncRoot는 권장하지 않습니다. http://blogs.msdn.com/brada/archive/2003/09/28/50391.aspx –

+0

@_NT : 블로그 게시물에서 인용 : "우리는 이러한 컬렉션의 제네릭 버전을 빌드하는 것과 같은 실수를 저 지르지 않을 것이라고 확신합니다."MSDN에 낙담하지 않고 목록 .SyncRoot를 사용하여 6 년 후, 여기 있습니다. http://msdn.microsoft.com/en-us/library/bb356596.aspx –

6

가짜 결과가 발생할 수 있습니다 따라서, 당신의 Client 클래스 SyncRoot 속성을 노출하고 호출 코드에서 해당에 고정하는 것이 훨씬 더 좋을 것이다. 예를 들어, 다음 코드를 살펴 :

class C { 
    private object mylock = new object(); 

    public int A { 

     get { 
     int result; 
     lock(mylock) { 
     result = mA; 
     } 
     return result; 
     } 

     set { 
     lock(mylock) { 
      mA = value; 
     } 
     } 
    } 
} 
C obj = new C; 
C.A++; 

가 (예, 나는 첫 번째 대답에서 그것을 복사 한) 여기에 경쟁 조건이 있습니다! "C.A ++"연산은 실제로 A에 두 개의 별도 액세스를 요구하는데, 하나는 값을 얻고 다른 하나는 업데이트 된 값을 설정하는 것입니다. 이 두 가지 액세스가 컨텍스트 전환없이 함께 수행되도록하는 것은 없습니다. 경쟁 조건에 대한 고전적인 시나리오!

그래서주의하십시오! 접근 자 안에 자물쇠를 넣는 것은 좋지 않습니다. 이전 답변에서와 같이 자물쇠를 명시 적으로 가져와야합니다 (SyncRoot와 함께 할 필요는 없지만 모든 객체가 수행합니다)

+0

또한 코드에있는 모든 호출에 lock 객체를 수동으로 추가한다는 의미입니까? 적어도 20 개의 판독 값과 15 개의 기록이 있습니다. – Petr

+0

전체 중요 영역을 포괄하도록 자물쇠를 확장하려면, –

+0

NT : 잘 모르겠다. 다른 인스턴스에서 해당 변수를 사용하여 다른 작업을하는 약 15 개의 메서드가 있습니다. 어떻게 loc 케이. 이상 올바르게 읽으면 속성 잠금이 좋지 않습니다. – Petr

관련 문제