2009-09-07 15 views
8

Tôi chỉ tự hỏi liệu mã này mà một nhà phát triển đồng nghiệp (người đã rời khỏi) là OK, tôi nghĩ rằng ông muốn tránh đặt một khóa. Có một sự khác biệt hiệu suất giữa điều này và chỉ sử dụng một khóa thẳng về phía trước?Lồng vào nhau được sử dụng để tăng/mimick một boolean, điều này có an toàn không?

private long m_LayoutSuspended = 0; 
    public void SuspendLayout() 
    { 
     Interlocked.Exchange(ref m_LayoutSuspended, 1); 
    } 

    public void ResumeLayout() 
    { 
     Interlocked.Exchange(ref m_LayoutSuspended, 0); 
    } 

    public bool IsLayoutSuspended 
    { 
     get { return Interlocked.Read(ref m_LayoutSuspended) != 1; } 
    } 

Tôi đã nghĩ rằng điều gì đó như thế sẽ dễ dàng hơn với khóa? Nó thực sự sẽ được sử dụng bởi nhiều chủ đề, do đó tại sao việc sử dụng khóa/lồng vào nhau đã được quyết định.

Trả lời

8

Cá nhân tôi muốn sử dụng một Boolean dễ bay hơi:

private volatile bool m_LayoutSuspended = false; 
public void SuspendLayout() 
{ 
    m_LayoutSuspended = true; 
} 

public void ResumeLayout() 
{ 
    m_LayoutSuspended = false; 
} 

public bool IsLayoutSuspended 
{ 
    get { return m_LayoutSuspended; } 
} 

Sau đó, một lần nữa, như tôi vừa mới thừa nhận ở nơi khác, biến động không có nghĩa là hoàn toàn những gì tôi nghĩ rằng nó đã làm. Tôi nghi ngờ điều này là okay mặc dù :)

Thậm chí nếu bạn gắn bó với Interlocked, tôi muốn đổi thành int ... không cần phải làm cho hệ thống 32 bit có khả năng đấu tranh để tạo 64 bit viết nguyên tử khi họ có thể làm điều đó một cách dễ dàng với 32 bit ...

+0

@Jon: Tôi tò mò, bạn có thể xây dựng trên "biến động không có nghĩa là hoàn toàn những gì tôi nghĩ rằng nó đã làm"? – LukeH

+0

@Luke: Tôi đang lên kế hoạch xây dựng chi tiết về bài đăng trên blog tại một số thời điểm, nhưng http://www.bluebytesoftware.com/blog/2008/06/13/VolatileReadsAndWritesAndTimeliness.aspx là phần lớn trong số đó. –

+0

Chỉ cần nhấn mạnh, độ dài dễ bay hơi sẽ không ** an toàn (trên hệ thống 32 bit). –

13

có gì bạn đang làm là an toàn từ một điểm chủng tộc của xem đạt lĩnh vực m_LayoutSuspended, tuy nhiên, một khóa là cần thiết vì lý do sau nếu mã nào sau đây:

if (!o.IsLayoutSuspended) // This is not thread Safe ..... 
{ 
    o.SuspendLayout(); // This is not thread Safe, because there's a difference between the checck and the actual write of the variable a race might occur. 
    ... 
    o.ResumeLayout(); 
} 

Cách an toàn hơn, sử dụng CompareExchange để đảm bảo không có chủng tộc các điều kiện đã xảy ra:

private long m_LayoutSuspended = 0; 
public bool SuspendLayout() 
{ 
    return Interlocked.CompareExchange(ref m_LayoutSuspended, 1) == 0; 
} 

if (o.SuspendLayout()) 
{ 
    .... 
    o.ResumeLayout(); 
} 

Hoặc tốt hơn là chỉ cần sử dụng khóa.

+0

[Interlocked.CompareExchange không có quá tải với hai đối số ] (https://msdn.microsoft.com/en-us/library/system.threading.interlocked (v = vs.110) .aspx) có lẽ dòng của bạn nên đọc 'return Interlocked.CompareExchange (ref m_LayoutSuspended, 1, 0) == 0; ' –

+0

Nó có [cũng được chỉ ra cho tôi] (https://meta.stackoverflow.com/questions/320996/changed-edit-still-doesnt-compile#comment333601_320996) thay đổi nó thành' return Interlocked.Exchange (ref m_LayoutSuspended, 1) == 0; 'cũng sẽ thực hiện thủ thuật. –

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