简体   繁体   中英

Any Concurrency Issues with my code

I a trying to create a thread-safe method.

Does anyone see any concurrency issues with following code?

To me it seems fine , though I could never find a way to test for concurrency on this method. Any help would be appreciated.

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

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

Considering you'e lock ing around an appropriately-scoped object, I see no concurrency issues with your code.

However, as millimoose mentioned in the comments, you have a potential performance problem. If two threads try to LogToTextFile at the same time, one is going get the lock first, and the other is going to block while the file is opened, written to, and then closed. This may not be acceptable, depending on what your threads are doing.

If what I mention is a problem, you'll have to implement a more complex thread-safe logger. Typically there would be a queue to which log events are quickly written. Then there is another thread who periodically wakes up, and empties the queue to the file on disk. All operations on the queue are done with a lock.

Another, possibly better solution may be to leave the file opened, and use a synchronized TextWriter to perform the writes. TextWriter.Synchronized provides a thread-safe wrapper around a TextWriter :

All write operations to the returned wrapper will be thread safe. You call this method to ensure that only one thread at a time can execute the methods on the TextWriter instance that is returned.

Here's a simple implementation. Note, this has not been tested.

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

There are no concurrency issues within this specific function. The lock statement will properly moderate access to the inner code.

However there are still potential concurrency issues with accessing @"c:\\logs\\log1.txt" . It's possible that another part of your application, or another process on the same machine, will try to write to the file at the same time as your code. Hence it's possible the StreamWriter code will fail even with this lock.

There is no way to work around this type of concurrency issues. The file system is a shared resource that you have no true capability to protect. Instead your code needs to accept that the file system access can fail and properly handle that consequence.

Typically when dealing with logging functions I wrap file system access with a try / catch and swallow any exceptions that occur. Otherwise you run the risk of a logging function failure taking down an application. That may or may not be acceptable for your scenario.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM