Синхронизация трех потоков - C#

184
06 марта 2018, 01:19

Есть три потока:

  1. Возвращает положительные нечетные числа
  2. Возвращает положительные четные числа
  3. Возвращает все отрицательные числа

Имеется также диапазон от -100 до 100. Нужно, чтобы в результате работы всех трех потоков список содержал все эти числа в порядке возрастания. Все три потока опираются на один метод.

Код:

class Program
{
    static object locker = new object();
    static void Main(string[] args)
    {
        Thread thread1 = new Thread(Add);
        Thread thread2 = new Thread(Add);
        Thread thread3 = new Thread(Add);
        thread1.Name = "thread1_odd";
        thread2.Name = "thread2_even";
        thread3.Name = "thread3_neg";
        thread1.Start();
        thread2.Start();
        thread3.Start();
        thread1.Join();
        thread2.Join();
        thread3.Join();
        Node node = List.First;
        while (node != null)
        {
            Console.WriteLine(node.Value);
            node = node.Next;
        }
    }
    static void Add()
    {
        for (int i = -100; i <= 100; i++)
        {
            lock (locker)
            {
                if (i >= 0 && i % 2 == 1 && Thread.CurrentThread.Name == "thread1_odd" 
                    || i >= 0 && i % 2 == 0 && Thread.CurrentThread.Name == "thread2_even" 
                    || i < 0 && Thread.CurrentThread.Name == "thread3_neg")
                {
                    Thread.Sleep(10);
                    List.Add(i);
                }
            }
        }
    }
}

На всякий случай, List - двусвязный список, который я реализовал самостоятельно.

Сначала должны добавляться в список отрицательные числа, потом по очереди четные-нечетные. Если оставить только положительные числа, то lock здесь справляется: выводит числа от 1 до 100 по порядку, - но в данном случае нужно учесть отрицательные числа и 0, а это значит, нужно блокировать первые два потока, пока работает третий, до тех пор, пока отрицательные числа не закончатся. Ну и с нулем что-то сделать, думаю, запустить сначала второй поток, потом первый. Но как это сделать в одном методе?

Answer 1

Вам нужен не один лок, вам нужно два семафора, которые автоматически закрываются после того, как дождались их сигнала (AutoResetEvent): один для четных и один для нечетных чисел. Они позволят вам чередовать вывод четных и нечетных чисел. Алгоритм получится следующим:

  1. Оба семафора в закрытом состоянии.
  2. thread3_neg выводит данные просто так. Когда доходит до -1, открывает четный семафор (т.к. согласно вашей проверке 0 -- четное число).
  3. thread1_odd выводит данные только когда четный семафор открыт. После вывода он открывает нечетный семафор и останавливается на снова закрытом четном семафоре.
  4. thread2_even выводит данные только когда нечетный семафор открыт. После вывода он открывает четный семафор и останавливается на снова закрытом нечетном семафоре.

Но вообще, если вы не делаете эту задачу для разминки ума, я бы посоветовал прислушаться к комментарию @Bulson: свалить вывод всех трех потоков в одну кучу, отсортировать и вывести. Не забудьте синхронизировать добавление в коллекцию или использовать потокобезопасную коллекцию.

READ ALSO
Каковы преимущества/недостатки Nemerle по сравнению с С#? [требует правки]

Каковы преимущества/недостатки Nemerle по сравнению с С#? [требует правки]

Здравствуйте! Большую часть времени я пишу на С#, но мне всегда не хватало в этом прекрасном языке макросов (однажды попробовав макросы LISP, трудно...

156
ChannelFactory очистка данных

ChannelFactory очистка данных

При передаче большого объема данных в WCF службу, передаваемое приложение начинает безмерно потреблять ОЗУ 240>364>478>797 Мб и тд

144
Обработка координат

Обработка координат

Я хочу запускать скрипт, когда мой объект в юнити, допустим, преодолеет 47f по координате "y" в 2д пространстве

148
SharpPcap проблема с размером пакета

SharpPcap проблема с размером пакета

Сразу начну с сути проблемы, я хочу отправить на устройство echo пакет и при создании пакета размером больше, чем 255, выдает ошибку

149