2010-07-21 4 views
8

나는 계층화 된 통신 인터페이스로 애플리케이션을 작성하고 있습니다.
이것은 응용 프로그램의 사용자 인터페이스 부분에서 통신을 추상화하고 더 확장 성/유지 보수성을 높이기 위해 수행되었습니다. 예를 들어
:C#의 레이스 조건 처리

alt text

위에 별도의 클래스로 그림에서 각 상자를 생각해 보자.
일반 Comms 인터페이스는 트랜잭션 데이터를 설명하는 문자열 변수를 채우고 일련의 공용 함수 호출을 통해 응용 프로그램에 복사되는 "상태"를 전달합니다.

class Application 
{ 
    private void SomeUpdateFunction() 
    { 
     this.textBox1.AppendText(this.AppSubSystem.GetText()); 
    } 
} 

class AppSubSystem 
{ 
    public string GetText() 
    { 
     return this.GenericCommsInterface.GetText(); 
    } 
} 

class GenericCommsInterface 
{ 
    public string GetText() 
    { 
     string sRetVal = this.sText; // sText is populated by other functions in the class. 
     this.sText = null; // Suspected race condition is here. 
     return sRetVal; 
    } 
} 

sText은 동급의 다른 기능에 의해 비동기 적으로 채워집니다 예를 들어, 응용 프로그램은 응용 프로그램 서브 - 시스템에 전화를 걸 것이다.
경쟁 조건이 string sRetVal = this.sText;과 다음 줄인 this.sText = null; 사이에 발생했습니다.
누군가이 경쟁 조건을 피하거나 방지하는 방법을 제안 할 수 있습니까? StringBuilder 도움말을 사용 하시겠습니까? 아니면 내가이 작업을 수행해야하는 다른 방법이 있습니까? 당신의 세트

lock(someObject) 
{ 
    //... 
    this.sText = value; 
} 

답변

4

this.sText을 터치 할 때마다 업데이트 기능과 GetText 기능을 사용해야합니다. 이렇게하면 한 번에 하나의 스레드 만이 문제를 일으키고, 다른 스레드는 현재 스레드가 완료 될 때까지 대기하고 대기합니다.

StringBuilder를 사용하는 것이 좋습니다. 일부는 잠김을 단순화하기 위해 잠긴 문자열을 잠 그거나 잠긴 작업의 중간에 전환 한 문자열을 외부 사용자의 관점에서 잠글 수 있습니다. 진짜 나쁜 모조를 일으킨다. 당신이 this에 잠글 수있다, 또는

lock (this.sbText) 
{ 
    sRetVal = this.sbText.ToString(); 
    this.sbText.Length = 0; 
} 

을, 그러나 그것은 추한 - 당신의 잠금 장치 안에 있어야 가능한 비공개로, 다른 경우와 같은 (이상한 부작용을 방지하기 위해이 같은 뭔가 도움이 될 것이다 개체가이 개체에 대한 잠금을 획득하려고 시도했습니다. sbText이 변경되는 동안 그렇게 할 수 없습니다.

+1

스레드 접근에서 안정적이지 않을 것이라는 보장이없는 객체에 '잠그는'것은 매우 좋지 않습니다. 잠금은 모든 사람들이 사용해야한다는 점에서 '권고'입니다. 잠금 개체를 계속 변경하기 때문에 잠금 개체를 포함하는 변수를 null로 설정하여 특히 바람직하지 않습니다. –

+0

좋은 지적.StringBuilder를 사용하는 또 다른 이유. – cHao

+0

팁 주셔서 감사합니다! 나는'private string sText'를'private StringBuilder cText'로 대체하고 잠금을 구현했습니다. 그것은 위대한 작품! 경쟁 조건이 사라졌습니다. 명성! –

1
public string GetText() 
{ 
    lock(someObject) 
    { 
     string sRetVal = this.sText; // sText is populated by other functions in the class. 
     this.sText = null; // Suspected race condition is here. 
     return sRetVal; 
    } 
}  

. 액세스하는 모든 사람을 잠글 필요가 있습니다.

+0

이렇게하면 * 않습니다 * - 새 문자열은 읽은 후 null 앞에 쓸 수 있습니다. 전체 작동은 부품뿐만 아니라 보호되어야합니다. –

+0

interning은 nether 지역에서 당신을 물 것입니다. 문자열을 잠그는 것은 전혀 잠그지 않는 것보다 더 나쁩니다. –

+0

나는 동의하지 않지만, 자물쇠 객체를 문자열로 정의하지는 않는다. 나는 그가 물건의 요지를 가지고 공란을 채울 수 있다고 생각하고 있었다. –

1

당신이 Te xt와 보호하지 않는 한이 코드는 가장 확실히 스레드 환경에서 작동하지 않습니다에

+1

작동합니다 - * 가끔 *. 다른 때에는 메시지가 신비하게 사라집니다. – cHao

+1

가끔씩 일하는 것이 효과가 없습니다. –

+3

저는 하루에 8 시간 씩 일합니다. 실업 상태에요? :) –