C#我正確使用鎖嗎?

[英]C# Am i using lock correctly?


I'm currently trying to write a thread-safe logger class. I'm not very familiar with correct design and best practices in this area. Is there a flaw in my code?

我目前正在嘗試編寫一個線程安全的記錄器類。我對這個領域的正確設計和最佳實踐不是很熟悉。我的代碼中有缺陷嗎?

public class WriteStuff
{
    private readonly StreamWriter m_Writer;
    private readonly object m_WriteLock = new object ();

    public WriteStuff(String path)
    {
        m_Writer = File.CreateText (path);

        m_Writer.WriteLine ("x");
        m_Writer.Flush ();
    }

    public void ListenTo(Foo foo)
    {
        foo.SomeEvent += new EventHandler<SomeArgs> (Foo_Update);
    }

    private void Foo_Update(object sender, SomeArgs args)
    {
        lock (m_WriteLock) {
            m_Writer.WriteLine (args);
            m_Writer.Flush ();
        }
    }
}

3 个解决方案

#1


What you've posted looks fine from a multi-threading perpective. Although I could be wrong, it would appear that any other code that does some multi-threading (even using the foo object) should be safe. Certainly, I can't see any deadlocks in the that section of code.

您發布的內容從多線程角度看起來很好。雖然我可能是錯的,但似乎任何其他執行某些多線程的代碼(即使使用foo對象)都應該是安全的。當然,我在代碼段中看不到任何死鎖。

A few things worth noting anyway (apart from being very careful with deadlocks and testing rigourously to insure they won't occur):

還有一些值得注意的事情(除了非常小心死鎖和嚴格測試以確保它們不會發生):

  • It's best to put a lock around the code within the constructor, as I believe it's possible in certain circumstances that methods can be called before the constructor block has finished executing. (Someone please correct me if I'm wrong on this one.)
  • 最好在構造函數中對代碼進行鎖定,因為我相信在某些情況下可以在構造函數塊執行完畢之前調用方法。 (如果我錯了,請有人糾正我。)

  • The StreamWriter object in this case is private, which is good. If it were protected or internal you would certainly have to be cautious about how other code utilised the object (in fact I think it would be best to almost always declare such objects as private).
  • 在這種情況下,StreamWriter對象是私有的,這很好。如果它是受保護的或內部的,你肯定必須小心其他代碼如何使用該對象(實際上我認為最好幾乎總是將這些對象聲明為私有)。

  • You've done locking the right way! It's always safest to lock on a separate private instance object because you know that object can't be locked by any other code than your own (which isn't the case if you lock this or the StreamWriter object itself).
  • 你已經完成了正確的鎖定!鎖定單獨的私有實例對象始終是最安全的,因為您知道該對象不能被您自己的任何其他代碼鎖定(如果您鎖定此對象或StreamWriter對象本身則不是這種情況)。

Still, I may be missing something, and there is a small possibility that some other code not shown above might cause problems, but as far as I can see it that code isn't flawed except for a possible missing lock around the constructor code. You're more likely to have to watch out for deadlock situations when you start doing more complex multi-threading, especially across classes/instances.

盡管如此,我可能會遺漏一些東西,並且上面沒有顯示的其他代碼可能會導致問題的可能性很小,但據我所知,除了構造函數代碼可能缺少鎖定之外,代碼沒有缺陷。當您開始執行更復雜的多線程時,尤其是跨類/實例,您更可能需要注意死鎖情況。

Anyway, hope that helps.

無論如何,希望有所幫助。

#2


Well, that looks OK to me; I'd probably implement IDisposable as a means to Close() the file, but...

嗯,這看起來對我好;我可能會將IDisposable實現為Close()文件的一種方法,但是......

Of course, you could also use any of the (many) pre-canned logging frameworks.

當然,您也可以使用任何(許多)預先封裝的日志框架。


Update:

One thought: you might want to consider what happens if the file already exists; you don't want to stomp on your logs...

一想法:您可能想要考慮如果文件已經存在會發生什么;你不想踩你的日志......

#3


The event handler is on the same thread as the event generator which means your app could end up being held up by your log file write.

事件處理程序與事件生成器位於同一個線程上,這意味着您的應用程序可能最終被日志文件寫入阻止。

private void Foo_Update(object sender, SomeArgs args)        { 
    ThreadPool.QueueUserWorkItem(WriteAsync, args);
}

private void WriteAsync(object state) {  
    SomeArgs args = (SomeArgs)state;    
    lock (m_WriteLock) {                        
       m_Writer.WriteLine (args);                        
       m_Writer.Flush ();                
   }        
}

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2009/04/06/83d5770501a52e24b0cf1fb5a1ae52d0.html



 
粤ICP备14056181号  © 2014-2020 ITdaan.com