private static bool TestSemaphoreInAProducerConsumerContext() { const int MIN_TIMEOUT = 0; const int MAX_TIMEOUT = 2; const int RUN_TIME = 30000; const int PRODUCER_THREADS = 1; const int CONSUMER_THREADS = 1; const int THREADS = PRODUCER_THREADS + CONSUMER_THREADS; Thread[] tthrs = new Thread[THREADS]; int[] privateCounters = new int[THREADS]; Semaphore__ freeSem = new Semaphore__(1); Semaphore__ dataSem = new Semaphore__(0); bool running = true; // Create and start consumer threads. for (int i = 0; i < CONSUMER_THREADS; i++) { int tid = i; tthrs[i] = new Thread(() => { Random rnd = new Random(tid); do { try { dataSem.Acquire(); } catch (ThreadInterruptedException) { break; } //Thread.Yield(); freeSem.Release(); if ((++privateCounters[tid] % 100) == 0) { Console.Write("[#c{0}]", tid); } else { try { Thread.Sleep(rnd.Next(MIN_TIMEOUT, MAX_TIMEOUT)); } catch (ThreadInterruptedException) { break; } } } while (Volatile.Read(ref running)); }); tthrs[i].Priority = ThreadPriority.Highest; tthrs[i].Start(); } // Create and start producer threads. for (int i = CONSUMER_THREADS; i < THREADS; i++) { int tid = i; tthrs[i] = new Thread(() => { Random rnd = new Random(tid); do { try { freeSem.Acquire(); } catch (ThreadInterruptedException) { break; } // Thread.Yield(); dataSem.Release(); if ((++privateCounters[tid] % 100) == 0) { Console.Write("[#p{0}]", tid - CONSUMER_THREADS); } else { try { Thread.Sleep(rnd.Next(MIN_TIMEOUT, MAX_TIMEOUT)); } catch (ThreadInterruptedException) { break; } } } while (Volatile.Read(ref running)); }); tthrs[i].Start(); } // run the test for a while Thread.Sleep(RUN_TIME); //Console.ReadLine(); Volatile.Write(ref running, false); Thread.Sleep(50); // Wait until all threads have been terminated. for (int i = 0; i < THREADS; i++) { if (tthrs[i].IsAlive) { tthrs[i].Interrupt(); } tthrs[i].Join(); } // Compute results Console.WriteLine("\nConsumer counters:"); int consumptions = 0; for (int i = 0; i < CONSUMER_THREADS; i++) { consumptions += privateCounters[i]; if (i != 0 && (i % 5) == 0) Console.WriteLine(); else Console.Write(' '); Console.Write("[#c{0}: {1,4}]", i, privateCounters[i]); } if (dataSem.Acquire(0)) { consumptions++; } Console.WriteLine("\nProducer counters:"); int productions = 0; for (int i = CONSUMER_THREADS; i < THREADS; i++) { productions += privateCounters[i]; if (i != CONSUMER_THREADS && ((i - CONSUMER_THREADS) % 5) == 0) { Console.WriteLine(); } else { Console.Write(' '); } Console.Write("[#p{0}: {1,4}]", i - CONSUMER_THREADS, privateCounters[i]); } Console.WriteLine("\nproductions: {0}, consumptios: {1}", productions, consumptions); return consumptions == productions; }
private static bool TestSemaphoreAsLock() { const int MIN_TIMEOUT = 0; const int MAX_TIMEOUT = 10; const int RUN_TIME = 10000; const int THREADS = 2; Thread[] tthrs = new Thread[THREADS]; int[] privateCounters = new int[THREADS]; int[] timeouts = new int[THREADS]; int sharedCounter = 0; Semaphore__ lockSem = new Semaphore__(1); for (int i = 0; i < THREADS; i++) { int tid = i; tthrs[i] = new Thread(() => { Random rnd = new Random(tid); int endTime = Environment.TickCount + RUN_TIME; do { do { try { if (lockSem.Acquire(Timeout.Infinite /*rnd.Next(MAX_TIMEOUT)*/)) { break; } //Console.Write('+'); timeouts[tid]++; } catch (ThreadInterruptedException) {} } while (true); sharedCounter++; Thread.Yield(); lockSem.Release(); if ((++privateCounters[tid] % 100) == 0) { Console.Write("[#{0}]", tid); } else { Thread.Sleep(rnd.Next(MIN_TIMEOUT, MAX_TIMEOUT)); } } while (Environment.TickCount < endTime); }); tthrs[i].Start(); } // Wait until all threads have been terminated. for (int i = 0; i < THREADS; i++) tthrs[i].Join(); // Compute results Console.WriteLine("\nPrivate counters:\n"); int sum = 0; for (int i = 0; i < THREADS; i++) { sum += privateCounters[i]; if ((i % 5) == 0) Console.WriteLine(); else Console.Write(' '); Console.Write("[#{0}: {1,4}/{2}]", i, privateCounters[i], timeouts[i]); } return sum == sharedCounter; }