C# 当多个线程写入同一个文件时会产生什么负面影响?

C# 当多个线程写入同一个文件时会产生什么负面影响?,c#,.net,multithreading,.net-2.0,integration-testing,C#,.net,Multithreading,.net 2.0,Integration Testing,以下是失败的集成测试的伪代码: [测试] void TestLogger() // Init static logger Logger.Init(pathToFile); // Create five threads that will call LogMessages delegate for i = 1 to 5 { Thread aThread = new Thread(LogMessages) aThread.Sta

以下是失败的集成测试的伪代码:

[测试]

void TestLogger()
    // Init static logger
    Logger.Init(pathToFile);

    // Create five threads that will call LogMessages delegate
    for i = 1 to 5 
    {
       Thread aThread = new Thread(LogMessages)
       aThread.Start(i);
    }

    // let threads complete their work
    Thread.Sleep(30000);

    /// read from log file and count the lines
    int lineCount = GetLineCount();

    // 5 threads, each logs 5 times = 25 lines in the log
    Assert.Equal(25, lineCount);


static void LogMessages( object data )
  // each thread will log five messages
  for i = 1 to 5 
  Logger.LogMessage(i.ToString() + " " + DateTime.Now.Ticks.ToString());
  Thread.Sleep(50);
每次运行测试时,行数似乎都会发生变化。有时行数是23行,有时是25行


在我仔细研究了一下代码之后,我注意到日志文件同时被多个线程访问(通过tick count验证是否相同)。对该文件的访问没有锁定,但同时我没有看到抛出异常。有人能解释为什么两次运行之间的日志行计数不一致吗?此外,这是由多个线程同时写入同一文件的负面影响吗?

众所周知,竞争条件是不可预测的。你永远不知道有多少写操作不能正常工作——有时甚至可能工作得非常好。是的,如果没有同步,从多个线程写入同一个文件,这是一种负面影响。

如果您试图使用Environment.TickCount验证同时性,那么您的时间会很糟糕。它只有大约15毫秒(IIRC)的精度,因此如果两个线程的值相同,那么您真正知道的就是它们彼此之间的日志记录间隔在15毫秒以内


如果您的Logger类在其对日志文件的访问周围设置了一个锁,那么这就足够了。只需通过
private static readonly object sync=new object()创建一个同步对象
然后执行
锁定(同步){…打开/读取/写入文件…}
。否则,无论您使用何种类型的流,您都将受制于线程安全性(提示:通常它们不是线程安全的)。

处理此类生产者/消费者死锁和其他竞争条件的最简单方法可能是调用lock()内置:

这将阻止其他线程。您还可以使用上面简要提到的同步锁定样式。这家伙的网站上有一个很好的例子,说明了所有可用的选项(以及优缺点):


祝你好运。

通常,多线程日志记录是通过将日志条目(阻塞生产者-消费者队列)排队到一个写入磁盘的记录器线程来执行的。这会将锁定时间降低到将*日志项推送到队列上所需的时间:几乎没有争用。队列吸收任何磁盘延迟、网络延迟等


使用简单的锁会对所有调用线程造成任何磁盘/网络延迟/延迟。

要添加到上面的答案中,如果线程1获得a,并将B添加到a。然后线程2进入并获得a,将C添加到其中。线程1将AB保存到文件中,但由于线程2已读取该文件,因此当它重写该文件时,该文件将只包含AC而不是ABC。。。和简单性相比,它的性能很差。10毫秒的搜索将对所有试图登录的应用程序线程造成10毫秒的阻塞-进入的线程正在等待磁盘IO,其他线程正在等待锁定。
lock(Logger){
 //use your logger here
}