Zakleszczenie - ManualResetEvent

Zakleszczenie - ManualResetEvent
  • Rejestracja: dni
  • Ostatnio: dni
0

Witam, ćwiczę sobie programowanie równoległe i napotkałem takie zadanie:
Korzystając z ManualResetEventSlim, przygotuj program, w którym dwa wątki przekazują sobie "pałeczkę" uprawniającą je do działania. Przy uruchomieniu aplikacji włączy się pierwszy wątek; drugi czeka. Po sekundzie pierwszy wątek wstrzymuje działanie i daje kontrole drugiemu wątkowi. Po kolejnej sekundzie drugi wątek wstrzymuje działanie i daje sygnał do działania pierwszemu wątkowi. I tak aż do momentu, w którym użytkownik zakończy program.

Wszystko pięknie działa jak dodam thread.Sleep(1000) przed Console.WriteLine. Problem mam natomiast jak usunę Thread.Sleep. Pojawia się zakleszczenie i program losowo po "n" rundzie przestaje działać. Jakieś pomysły ?

Kopiuj
using System;
using System.Threading;

namespace ManualResetEventSlimExample
{
    public class Program
    {
        public static void Main(string[] args)
        {
            ManualResetEvent threadOneController = new ManualResetEvent(true);
            ManualResetEvent threadTwoController = new ManualResetEvent(false);

            ThreadStart action1 = new ThreadStart(() =>
            {
                while (true)
                {
                    threadOneController.WaitOne();
                    Thread.Sleep(0);
                    Console.WriteLine("{0} --- Thread 1 is doing some actions", DateTime.Now);
                    threadTwoController.Set();
                    threadTwoController.Reset();
                    threadOneController.Reset();
                }
            });

            ThreadStart action2 = new ThreadStart(() =>
            {
                while (true)
                {
                    threadTwoController.WaitOne();
                    Thread.Sleep(0);
                    Console.WriteLine("{0} --- Thread 2 is doing some actions", DateTime.Now);
                    threadOneController.Set();
                    threadOneController.Reset();
                    threadTwoController.Reset();
                }
            });

            var t1 = new Thread(action1);
            var t2 = new Thread(action2);

            t1.Start();
            t2.Start();
        }
    }
}
xeo545x39
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Kosmos
  • Postów: 1571
0

Moim zdaniem chodzi tu o to, że gdy nie ma żadnego oczekiwania i operacji zajmującej czas to...
Thread1 - robi Set, drugi wątek "startuje".
Thread2 - w tym samym czasie po starcie (WaitOne) robi się Set na 1 i Resety wykonują się w tym samym czasie gdy jeszcze tam wykonuje się własnie kod na etapie Resetów
Nie przewidzisz w którym momencie wykona się równocześnie, więc moim zdaniem o to chodzi, że nierówno wykona się kod i nawzajem się zblokują dzięki Resetom wywołanym nawzajem siebie.

DibbyDum
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Polska, Kraków
1

Chyba namieszałeś sobie z tymi resetami i kolejnością:

Kopiuj
public static void Main(string[] args)
{
   ManualResetEvent threadOneController = new ManualResetEvent(true);
   ManualResetEvent threadTwoController = new ManualResetEvent(false);

   ThreadStart action1 = () =>
   {
      while (true)
      {
         threadOneController.WaitOne();
         //Thread.Sleep(1000);
         Console.WriteLine("{0} --- Thread 1 is doing some actions", DateTime.Now);
         threadOneController.Reset();
         threadTwoController.Set();
      }
   };

   ThreadStart action2 = () =>
   {
      while (true)
      {
         threadTwoController.WaitOne();
         //Thread.Sleep(1000);
         Console.WriteLine("{0} --- Thread 2 is doing some actions", DateTime.Now);
         threadTwoController.Reset();
         threadOneController.Set();
      }
   };

   var t1 = new Thread(action1);
   var t2 = new Thread(action2);

   t1.Start();
   t2.Start();
}

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.