using System;
using System.Threading;
using static System.Console;
namespace Chapter2.Recipe1
{
internal class Program
{
private static void Main(string[] args)
{
WriteLine("Incorrect counter");
var c = new Counter();
var t1 = new Thread(() => TestCounter(c));
var t2 = new Thread(() => TestCounter(c));
var t3 = new Thread(() => TestCounter(c));
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();
WriteLine($"Total count: {c.Count}");
WriteLine("--------------------------");
WriteLine("Correct counter");
var c1 = new CounterNoLock();
t1 = new Thread(() => TestCounter(c1));
t2 = new Thread(() => TestCounter(c1));
t3 = new Thread(() => TestCounter(c1));
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();
WriteLine($"Total count: {c1.Count}");
}
static void TestCounter(CounterBase c)
{
for (int i = 0; i < 100000; i++)
{
c.Increment();
c.Decrement();
}
}
class Counter : CounterBase
{
private int _count;
public int Count => _count;
public override void Increment()
{
_count++;
}
public override void Decrement()
{
_count--;
}
}
class CounterNoLock : CounterBase
{
private int _count;
public int Count => _count;
public override void Increment()
{
Interlocked.Increment(ref _count);
}
public override void Decrement()
{
Interlocked.Decrement(ref _count);
}
}
abstract class CounterBase
{
public abstract void Increment();
public abstract void Decrement();
}
}
}
using System;
using System.Threading;
using static System.Console;
namespace Chapter2.Recipe2
{
class Program
{
static void Main(string[] args)
{
const string MutexName = "CSharpThreadingCookbook";
using (var m = new Mutex(false, MutexName))
{
if (!m.WaitOne(TimeSpan.FromSeconds(5), false))
{
WriteLine("Second instance is running!");
}
else
{
WriteLine("Running!");
ReadLine();
m.ReleaseMutex();
}
}
}
}
}
using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;
namespace Chapter2.Recipe3
{
class Program
{
static void Main(string[] args)
{
for (int i = 1; i <= 6; i++)
{
string threadName = "Thread " + i;
int secondsToWait = 2 + 2 * i;
var t = new Thread(() => AccessDatabase(threadName, secondsToWait));
t.Start();
}
}
static SemaphoreSlim _semaphore = new SemaphoreSlim(4);
static void AccessDatabase(string name, int seconds)
{
WriteLine($"{name} waits to access a database");
_semaphore.Wait();
WriteLine($"{name} was granted an access to a database");
Sleep(TimeSpan.FromSeconds(seconds));
WriteLine($"{name} is completed");
_semaphore.Release();
}
}
}
using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;
namespace Chapter2.Recipe4
{
class Program
{
static void Main(string[] args)
{
var t = new Thread(() => Process(10));
t.Start();
WriteLine("Waiting for another thread to complete work");
_workerEvent.WaitOne();
WriteLine("First operation is completed!");
WriteLine("Performing an operation on a main thread");
Sleep(TimeSpan.FromSeconds(5));
_mainEvent.Set();
WriteLine("Now running the second operation on a second thread");
_workerEvent.WaitOne();
WriteLine("Second operation is completed!");
}
private static AutoResetEvent _workerEvent = new AutoResetEvent(false);
private static AutoResetEvent _mainEvent = new AutoResetEvent(false);
static void Process(int seconds)
{
WriteLine("Starting a long running work...");
Sleep(TimeSpan.FromSeconds(seconds));
WriteLine("Work is done!");
_workerEvent.Set();
WriteLine("Waiting for a main thread to complete its work");
_mainEvent.WaitOne();
WriteLine("Starting second operation...");
Sleep(TimeSpan.FromSeconds(seconds));
WriteLine("Work is done!");
_workerEvent.Set();
}
}
}
using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;
namespace Chapter2.Recipe5
{
class Program
{
static void Main(string[] args)
{
var t1 = new Thread(() => TravelThroughGates("Thread 1", 5));
var t2 = new Thread(() => TravelThroughGates("Thread 2", 6));
var t3 = new Thread(() => TravelThroughGates("Thread 3", 12));
t1.Start();
t2.Start();
t3.Start();
Sleep(TimeSpan.FromSeconds(6));
WriteLine("The gates are now open!");
_mainEvent.Set();
Sleep(TimeSpan.FromSeconds(2));
_mainEvent.Reset();
WriteLine("The gates have been closed!");
Sleep(TimeSpan.FromSeconds(10));
WriteLine("The gates are now open for the second time!");
_mainEvent.Set();
Sleep(TimeSpan.FromSeconds(2));
WriteLine("The gates have been closed!");
_mainEvent.Reset();
}
static void TravelThroughGates(string threadName, int seconds)
{
WriteLine($"{threadName} falls to sleep");
Sleep(TimeSpan.FromSeconds(seconds));
WriteLine($"{threadName} waits for the gates to open!");
_mainEvent.Wait();
WriteLine($"{threadName} enters the gates!");
}
static ManualResetEventSlim _mainEvent = new ManualResetEventSlim(false);
}
}
using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;
namespace Chapter2.Recipe6
{
class Program
{
static void Main(string[] args)
{
WriteLine("Starting two operations");
var t1 = new Thread(() => PerformOperation("Operation 1 is completed", 4));
var t2 = new Thread(() => PerformOperation("Operation 2 is completed", 8));
t1.Start();
t2.Start();
_countdown.Wait();
WriteLine("Both operations have been completed.");
_countdown.Dispose();
}
static CountdownEvent _countdown = new CountdownEvent(2);
static void PerformOperation(string message, int seconds)
{
Sleep(TimeSpan.FromSeconds(seconds));
WriteLine(message);
_countdown.Signal();
}
}
}
using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;
namespace Chapter2.Recipe7
{
class Program
{
static void Main(string[] args)
{
var t1 = new Thread(() => PlayMusic("the guitarist", "play an amazing solo", 5));
var t2 = new Thread(() => PlayMusic("the singer", "sing his song", 2));
t1.Start();
t2.Start();
}
static Barrier _barrier = new Barrier(2,
b => WriteLine($"End of phase {b.CurrentPhaseNumber + 1}"));
static void PlayMusic(string name, string message, int seconds)
{
for (int i = 1; i < 3; i++)
{
WriteLine("----------------------------------------------");
Sleep(TimeSpan.FromSeconds(seconds));
WriteLine($"{name} starts to {message}");
Sleep(TimeSpan.FromSeconds(seconds));
WriteLine($"{name} finishes to {message}");
_barrier.SignalAndWait();
}
}
}
}
using System;
using System.Collections.Generic;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;
namespace Chapter2.Recipe8
{
class Program
{
static void Main(string[] args)
{
new Thread(Read){ IsBackground = true }.Start();
new Thread(Read){ IsBackground = true }.Start();
new Thread(Read){ IsBackground = true }.Start();
new Thread(() => Write("Thread 1")){ IsBackground = true }.Start();
new Thread(() => Write("Thread 2")){ IsBackground = true }.Start();
Sleep(TimeSpan.FromSeconds(30));
}
static ReaderWriterLockSlim _rw = new ReaderWriterLockSlim();
static Dictionary<int, int> _items = new Dictionary<int, int>();
static void Read()
{
WriteLine("Reading contents of a dictionary");
while (true)
{
try
{
_rw.EnterReadLock();
foreach (var key in _items.Keys)
{
Sleep(TimeSpan.FromSeconds(0.1));
}
}
finally
{
_rw.ExitReadLock();
}
}
}
static void Write(string threadName)
{
while (true)
{
try
{
int newKey = new Random().Next(250);
_rw.EnterUpgradeableReadLock();
if (!_items.ContainsKey(newKey))
{
try
{
_rw.EnterWriteLock();
_items[newKey] = 1;
WriteLine($"New key {newKey} is added to a dictionary by a {threadName}");
}
finally
{
_rw.ExitWriteLock();
}
}
Sleep(TimeSpan.FromSeconds(0.1));
}
finally
{
_rw.ExitUpgradeableReadLock();
}
}
}
}
}
using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;
namespace Chapter2.Recipe9
{
class Program
{
static void Main(string[] args)
{
var t1 = new Thread(UserModeWait);
var t2 = new Thread(HybridSpinWait);
WriteLine("Running user mode waiting");
t1.Start();
Sleep(20);
_isCompleted = true;
Sleep(TimeSpan.FromSeconds(1));
_isCompleted = false;
WriteLine("Running hybrid SpinWait construct waiting");
t2.Start();
Sleep(5);
_isCompleted = true;
}
static volatile bool _isCompleted = false;
static void UserModeWait()
{
while (!_isCompleted)
{
Write(".");
}
WriteLine();
WriteLine("Waiting is complete");
}
static void HybridSpinWait()
{
var w = new SpinWait();
while (!_isCompleted)
{
w.SpinOnce();
WriteLine(w.NextSpinWillYield);
}
WriteLine("Waiting is complete");
}
}
}