0

我试图创建一个线程安全的方法。

有人看到以下代码有任何并发​​问题吗?

对我来说这似乎很好,尽管我永远无法找到一种方法来测试这种方法的并发性。任何帮助,将不胜感激。

   //static locker for thread synchronization
   private static readonly System.Object _object3 = new System.Object();

   //this method needs to be thread-safe
   public static void LogToTextFile(string logMessage, LogLevel logType)
    {
       //make sure only one thread executes this file writing code at a time            
       lock (_object3)
        {
            using (StreamWriter w = File.AppendText(@"c:\logs\log1.txt");
            {
                w.WriteLine("\r\n{0} logged at {1} {2} : {3}", logType.ToString().ToUpper(), DateTime.Now.ToLongTimeString(), DateTime.Now.ToLongDateString(), logMessage);
            }
        }
    }
4

4 回答 4

3

此代码没有并发问题,因为由于 lock 语句,您只允许单个线程写入文件。

于 2013-03-09T23:27:56.913 回答
1

考虑到您正在lock使用范围适当的对象,我认为您的代码没有并发问题。

但是,正如评论中提到的那样,您有一个潜在的性能问题。如果两个线程同时尝试LogToTextFile,一个会先获得锁,另一个会在文件打开、写入和关闭时阻塞。这可能是不可接受的,具体取决于您的线程在做什么。

如果我提到的是一个问题,您将不得不实现一个更复杂的线程安全记录器。通常会有一个队列,日志事件会被快速写入。然后有另一个线程定期唤醒,并将队列清空到磁盘上的文件。队列上的所有操作都使用锁完成。

于 2013-03-09T23:31:02.883 回答
1

另一个可能更好的解决方案可能是让文件保持打开状态,并使用同步TextWriter来执行写入。 TextWriter.Synchronized为 a 提供了一个线程安全的包装器TextWriter

对返回的包装器的所有写操作都是线程安全的。您调用此方法以确保一次只有一个线程可以执行返回的 TextWriter 实例上的方法。

这是一个简单的实现。请注意,这尚未经过测试。

public static class MyLogger
{
    private static TextWriter s_writer;

    // Not thread-safe. Call this before other threads are allowed to call Log.
    public void Open(string filename) {
        s_writer = TextWriter.Synchronized( File.AppendText(filename) );
    }

    // Also not thread-safe.
    public void Close() {
       s_writer.Dispose();
    }

    // Thread-safe.
    public void Log(string logMessage, LogLevel logType) {
        s_writer.WriteLine("\r\n{0} logged at {1} {2} : {3}",
            logType.ToString().ToUpper(), DateTime.Now.ToLongTimeString(),
            DateTime.Now.ToLongDateString(), logMessage);
    }    
}
于 2013-03-09T23:48:35.110 回答
1

此特定函数中不存在并发问题。该lock语句将适当地调节对内部代码的访问。

但是,访问@"c:\logs\log1.txt". 您的应用程序的另一部分或同一台机器上的另一个进程可能会尝试与您的代码同时写入文件。因此,StreamWriter即使使用此锁,代码也可能会失败。

没有办法解决这种类型的并发问题。文件系统是您没有真正保护能力的共享资源。相反,您的代码需要接受文件系统访问可能失败并正确处理该后果。

通常在处理日志记录函数时,我用 a 包装文件系统访问try / catch并吞下发生的任何异常。否则,您将面临日志记录功能失败导致应用程序瘫痪的风险。对于您的方案,这可能会或可能不会接受。

于 2013-03-10T00:56:09.720 回答