Синхронизация процессов

#.net #process #synchronization #mutex

#.net #процесс #синхронизация #мьютекс

Вопрос:

Например, я создаю два процесса (ConsoleApplication2.exe ). Каждый из них записывает некоторый текст («dog» или «cat») в один и тот же текстовый файл: c:_threads_laboratorydata.txt . Я хочу получить результат:

собака,
кошка
,
кот
,
собака
,
собака
, кот

dog, кот

но я понимаю это:

собака
собаки
собаки
собаки
кота
собаки
кота
собаки
кота
собаки
кота
собаки
кота
собаки
кота

Почему я получаю неверный результат? Как я могу это исправить?

Мои процессы запускаются с помощью Launcher.exe:

 // Program.cs
// It builds the Launcher.exe
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Launcher {

  class Program {
    static void Main(string[] args) {

      Console.Title = "Launcher";
      String fileFullName = @"c:_threads_laboratorydata.txt";

      using (Mutex mutex = new Mutex(true, "my_mutex")) {

        if (File.Exists(fileFullName))
          File.Delete(fileFullName);

        Process proc_1 = new Process();
        String exeName = @".ConsoleApplication2.exe";
        ProcessStartInfo info_1 = new ProcessStartInfo(exeName, "proc_#1 dog");
        proc_1.StartInfo = info_1;
        proc_1.Start();
        Console.WriteLine("proc_#1 started by launcher...");

        Process proc_2 = new Process();
        ProcessStartInfo info_2 = new ProcessStartInfo(exeName, "proc_#2 cat");
        proc_2.StartInfo = info_2;
        proc_2.Start();
        Console.WriteLine("proc #2 started by launcher...");

        mutex.ReleaseMutex();

        proc_1.WaitForExit();
        proc_2.WaitForExit();
      }

      Console.WriteLine("Result in the "{0}" file.", fileFullName);
      Console.WriteLine("Press any key for exit...");
      Console.ReadKey();
    }
  }
}
  

ConsoleApplication2.exe код:

 // Program_2.cs
// It builds the ConsoleApplication2.exe
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace ConsoleApplication2 {

  class Program_2 {

    static void Main(string[] args) {
      if (2 != args.Length)
        return;

      Console.Title = args[0];

      Mutex mutex = new Mutex(false, "my_mutex");

      String dir = @"c:_threads_laboratory";
      String file = "data.txt";
      String fullName = Path.Combine(dir, file);
      if (!Directory.Exists(dir))
        Directory.CreateDirectory(dir);
      String text = args[1];
      Int32 counter = 100;

      using (FileStream fs = File.Open(fullName, FileMode.Append,
        FileAccess.Write, FileShare.ReadWrite)) {
        using (StreamWriter sw = new StreamWriter(fs)) {
          while (counter-- > 0) {
            mutex.WaitOne();
            fs.Position = fs.Length;
            sw.WriteLine(text);
            Console.Write("*");
            sw.Flush();
            fs.Flush(true);
            mutex.ReleaseMutex();
            Thread.Sleep(0);
          }
          sw.Close();
        }
        fs.Close();
      }
    }
  }
}
  

Комментарии:

1. Почему вы вообще ожидаете какой-либо синхронизации? Результат должен быть абсолютно случайным.

2. потому что я использую именованный мьютекс для синхронизации процессов.

Ответ №1:

Я думаю, что вы путаете мьютексы и события. «Мьютекс» — это сокращение от «Взаимоисключающий» — ваш код только гарантирует, что два процесса не будут записывать данные в файл одновременно.

Что вам действительно нужно, так это два события; способ для одного процесса сигнализировать, что это сделано и теперь ожидает другого, и другое событие для обратного хода.

Комментарии:

1. «Пожалуйста, обратите внимание, что события в Windows не полностью защищены от условий гонки». Не могли бы вы пояснить?

2. Именованные мьютексы могут использоваться для синхронизации не только потоков, но и процессов (Справочник по C #4.0 Герберта Шилдта).

Ответ №2:

Вы получили синхронизацию. Несинхронизированный результат был бы чем-то вроде

 docat
g
cat
cat
cadto
g
dog
catdog

cat
  

Комментарии:

1. Нет. Посмотрите внимательно на начало текстового файла.

2. @Bush: Вы полностью упустили разницу. В вашем примере выходные данные никогда не чередуются.