2010-07-21 49 views
8

Tôi đang viết một ứng dụng có giao diện truyền thông lớp.
Điều này được thực hiện để trừu tượng hóa các giao tiếp từ phần giao diện người dùng của ứng dụng và cũng để làm cho nó có khả năng mở rộng/duy trì hơn.
Ví dụ:Xử lý các điều kiện Race trong C#

alt text

xem xét mỗi hộp trong hình trên như là một lớp riêng biệt.
Giao diện chung của giao diện phổ biến các biến chuỗi mô tả dữ liệu được giao dịch và liên kết "sức khỏe", lần lượt được sao chép lên Ứng dụng thông qua một loạt các cuộc gọi chức năng công khai. Ví dụ, ứng dụng sẽ thực hiện cuộc gọi đến App-Sub-System:

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 là dân cư không đồng bộ bởi các chức năng khác trong lớp.
Tôi tin rằng tình trạng cuộc đua đang diễn ra giữa string sRetVal = this.sText; và dòng sau this.sText = null;.
Ai đó có thể đề xuất một cách để tránh hoặc ngăn chặn tình trạng cuộc đua này? Sẽ sử dụng trợ giúp StringBuilder hoặc có cách nào khác mà tôi nên thực hiện việc này không?

Trả lời

4

Có thể bạn nên mua khóa bất cứ lúc nào bạn muốn chạm vào this.sText - trong các chức năng cập nhật nó, cũng như chức năng GetText của bạn. Điều này sẽ đảm bảo rằng chỉ có một chủ đề tại một thời gian là rối tung với nó, như (giả sử thread của bạn có khóa) chủ đề khác sẽ ngồi và chờ đến khi thread hiện tại được thực hiện.

Tôi khuyên bạn nên sử dụng StringBuilder, một phần để đơn giản hóa khóa, như khóa chuỗi đã xảy ra hoặc được chuyển đổi ở giữa hoạt động bị khóa (và do đó được mở khóa, từ góc nhìn của người ngoài) gây ra mojo xấu. Something như thế này sẽ giúp:

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

Ngoài ra, bạn có thể khóa trên this, nhưng đó là xấu xí - ổ khóa của bạn nên được bên trong, như tin càng tốt, để tránh tác dụng phụ kỳ lạ (như nếu một số khác đối tượng đã cố gắng để có được một khóa trên đối tượng này - nó không thể làm như vậy trong khi sbText đã được thay đổi).

+1

Rất xấu để 'khóa' vào một đối tượng không được đảm bảo ổn định trong chuỗi truy cập - khóa là 'tư vấn' ở chỗ mọi người đều phải sử dụng/tôn trọng họ. Điều này đặc biệt xấu bởi vì bạn tiếp tục thay đổi đối tượng khóa (bằng cách đặt biến chứa nó thành null). –

+0

Điểm tốt.Một lý do khác để sử dụng một StringBuilder. – cHao

+0

Cảm ơn lời khuyên! Tôi đã thay thế 'private string sText' bằng' private StringBuilder cText' và triển khai các khóa. Nó hoạt động tuyệt vời! Tình trạng chủng tộc đã biến mất. Thanh danh! –

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; 
    } 
}  

trong thiết lập của bạn

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

Điều này sẽ * KHÔNG * làm điều đó - một chuỗi mới có thể được viết sau khi đọc nhưng trước giá trị rỗng. Toàn bộ hoạt động phải được bảo vệ, không chỉ các bộ phận. –

+0

interning sẽ cắn bạn trong các khu vực nether .. khóa trên một chuỗi là tồi tệ hơn không khóa ở tất cả. –

+0

Tôi không đồng ý, nhưng tôi đã không xác định đối tượng khóa của mình chút nào, hãy để một mình xác định nó là chuỗi. Tôi đã giả định anh ta có thể nắm lấy ý chính và điền vào chỗ trống. –

1

Mã này chắc chắn sẽ không làm việc trong một môi trường ren là bạn không bảo vệ stab. Bạn cần khóa tất cả mọi người truy cập vào nó.

+1

Nó sẽ hoạt động - * đôi khi *. Lần khác, tin nhắn sẽ biến mất một cách bí ẩn. – cHao

+1

Đôi khi làm việc không hoạt động. –

+3

Tôi làm việc 8 (ish) giờ một ngày. Tôi có thất nghiệp không? :) –

Các vấn đề liên quan