1 lock语句
public class SharedObject { private int _state; private object _syncObject = new object(); public int State { get { return _state; } } public void DoTheJob() { lock (_syncObject) { for (int i = 0; i < 50000; i++) { _state++; } } } } class Program { static void Main(string[] args) { int numTasks = 20; SharedObject sharedObject = new SharedObject(); var tasks = new Thread[numTasks]; for (int i = 0; i < numTasks; i++) { tasks[i] = new Thread(sharedObject.DoTheJob); tasks[i].Start(); } for (int i = 0; i < numTasks; i++) { tasks[i].Join(); } Console.WriteLine("summarized {0}", sharedObject.State); Console.Read(); } }
2 Monitor 类
C#的lock语句由编译器解析为使用Monitor类,Monitor提供TryEnter方法可以设置超时值
public class SharedObject { ...............
public void DoTheJob() { Monitor.TryEnter(_syncObject,50); try { for (int i = 0; i < 50000; i++) { _state++; } } finally { Monitor.Exit(_syncObject); } } }
3 SpinLock结构
对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁
public class SharedObject { private int _state; private SpinLock _lock = new SpinLock(); public int State { get { return _state; } } public void DoTheJob() { bool lockTaken = false; _lock.Enter(ref lockTaken); if (lockTaken) { try { for (int i = 0; i < 50000; i++) { _state++; } } finally { _lock.Exit(); } } } }
4 Mutex类
Mutex提供跨多个进程同步访问,如果指定名称,则由不同进程共享。
public class SharedObject { private int _state; private Mutex _mutex = new Mutex(false); public int State { get { return _state; } } public void DoTheJob() { _mutex.WaitOne(); try { for (int i = 0; i < 50000; i++) { _state++; } } finally { _mutex.ReleaseMutex(); } } }
bool createdNew; Mutex mutex = new Mutex(false, "SingleTonAppMutex",out createdNew); if (!createdNew) { Console.WriteLine("You can only start on instance"); }
5 Semaphore类
信号量 构造函数一个参数为最初释放的锁定数。
class Program { static void Main(string[] args) { int threadCount = 6; int semaphoreCount = 4; var semaphore = new SemaphoreSlim(0, semaphoreCount);
semaphore.Release(semaphoreCount); var threads = new Thread[threadCount]; for (int i = 0; i < threadCount; i++) { threads[i] = new Thread(ThreadMain); threads[i].Start(semaphore); } for (int i = 0; i < threadCount; i++) { threads[i].Join(); } Console.Read(); } static void ThreadMain(object o) { SemaphoreSlim semaphore = o as SemaphoreSlim; bool isCompleted = false; while (!isCompleted) { if (semaphore.Wait(600)) { try { Console.WriteLine("Thread {0} locks the semaphore", Thread.CurrentThread.ManagedThreadId); Thread.Sleep(2000); } finally { semaphore.Release(); Console.WriteLine("Thread {0} releases the semaphore", Thread.CurrentThread.ManagedThreadId); isCompleted = true; } } else { Console.WriteLine("Timeout for thread {0}:wait again", Thread.CurrentThread.ManagedThreadId); } } } }
6 Events类
ManualResetEvent,AutoResetEvent,ManualResetEventSlim,CountdownEvent
调用Set()方法,可向ManualResetEventSlim发信号。调用Reset()方法,可以使之返回不发信号状态。如果多个线程等待向一个事件发信号,并调用了Set()方法,就释放所有等待的线程。如果一个线程刚刚调用了WaitOne()方法,但事件已经发出信号,等待的线程就可以继续等待。
通过 Set()方法向AutoResteEvent发信号,当第一个线程等待状态结束时,该事件会自动变为不发信号的状态,这样,如果多个线程在等待向事件发信号,就只有一个线程结束其等待状态,它是优先级最高的线程。
public class Calculator { private ManualResetEventSlim _resetEvent; private int _id; public int Result { get; private set; } public Calculator(ManualResetEventSlim resetEvent,int id) { this._resetEvent = resetEvent; this._id = id; } public void Calculation(Object obj) { Tuple<int, int> data = (Tuple<int, int>)obj; Console.WriteLine("Calculator {0} starts calculation", _id); Thread.Sleep(new Random().Next(0,3000)); Result = data.Item1 + data.Item2; Console.WriteLine("Calculator {0} is ready", _id); _resetEvent.Set(); } } class Program { static void Main(string[] args) { int taskCount = 4; var resetEvents = new ManualResetEventSlim[taskCount]; var waitHandles = new WaitHandle[taskCount]; var calcs = new Calculator[taskCount]; TaskFactory taskFactory = new TaskFactory(); for (int i = 0; i < taskCount; i++) { resetEvents[i] = new ManualResetEventSlim(false); waitHandles[i] = resetEvents[i].WaitHandle; calcs[i] = new Calculator(resetEvents[i],i); taskFactory.StartNew(calcs[i].Calculation, Tuple.Create(i + 1, i + 3)); } for (int i = 0; i < taskCount; i++) { int index = WaitHandle.WaitAny(waitHandles); if (index == WaitHandle.WaitTimeout) { Console.WriteLine("Timeout!!"); } else { resetEvents[index].Reset(); Console.WriteLine("finished task for {0},result:{1}",index,calcs[index].Result); } } Console.Read(); }
}
CountdownEvent 用于把一些工作分支到多个任务中,并在以后合并结果。
public class Calculator { private CountdownEvent _cEvent; private int _id; public int Result { get; private set; } public Calculator(CountdownEvent cEvent, int id) { this._cEvent = cEvent; this._id = id; } public void Calculation(Object obj) { Tuple<int, int> data = (Tuple<int, int>)obj; Console.WriteLine("Calculator {0} starts calculation", _id); Thread.Sleep(new Random().Next(0,3000)); Result = data.Item1 + data.Item2; Console.WriteLine("Calculator {0} is ready", _id); _cEvent.Signal(); } } class Program { static void Main(string[] args) { int taskCount = 4; var cEvent = new CountdownEvent(taskCount);
var calcs = new Calculator[taskCount]; TaskFactory taskFactory = new TaskFactory(); for (int i = 0; i < taskCount; i++) { calcs[i] = new Calculator(cEvent, i); taskFactory.StartNew(calcs[i].Calculation, Tuple.Create(i + 1, i + 3)); } cEvent.Wait(); for (int i = 0; i < taskCount; i++) { Console.WriteLine("finished task for {0},result:{1}", i, calcs[i].Result); } Console.Read(); }
}
7 Barrier类
Barrier类非常适用于其中工作有多个任务分支且以后又需要合并工作的情况
public class CalculatorForBarrier { private Barrier _barrier; private int _id; public int Result { get; private set; } public CalculatorForBarrier(Barrier barrier, int id) { barrier.AddParticipant(); this._barrier = barrier; this._id = id; } public void Calculation(Object obj) { Tuple<int, int> data = (Tuple<int, int>)obj; Console.WriteLine("Calculator {0} starts calculation", _id); Thread.Sleep(3000); Result = data.Item1 + data.Item2; Console.WriteLine("Calculator {0} is ready", _id); _barrier.RemoveParticipant(); Console.WriteLine("Calculator {0} removed from barrier,remaining participants {1}", _id, _barrier.ParticipantsRemaining); } } class Program { static void Main(string[] args) { int taskCount = 2; Barrier barrier = new Barrier(1); var calcs = new CalculatorForBarrier[taskCount]; TaskFactory taskFactory = new TaskFactory(); for (int i = 0; i < taskCount; i++) { calcs[i] = new CalculatorForBarrier(barrier, i); taskFactory.StartNew(calcs[i].Calculation, Tuple.Create(i + 1, i + 3)); } barrier.SignalAndWait(); int sum = 0; for (int i = 0; i < taskCount; i++) { sum += calcs[i].Result; } Console.WriteLine("main finished {0}", sum); Console.WriteLine("remaining {0}", barrier.ParticipantsRemaining); Console.Read(); }
}
8 ReaderWriterLockSlim类
ReaderWriterLockSlim允许多个读取器访问资源,但只能有一个写入器锁定该资源,且读取的时候不能写,写入的时候不能读取
class Program { private static List<int> _items = new List<int>() { 0, 1, 2, 3, 4, 5 }; private static ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); static void ReaderMethod(object reader) { try { _lock.EnterReadLock(); for (int i = 0; i < _items.Count; i++) { Console.WriteLine("reader {0},loop:{1},item:{2}", reader, i, _items[i]); Thread.Sleep(40); } } finally { _lock.ExitReadLock(); } } static void WriterMethod(object writer) { try { while (!_lock.TryEnterWriteLock(50)) { Console.WriteLine("Writer {0} waiting for the writer lock", writer); Console.WriteLine("current reader count :{0}", _lock.CurrentReadCount); } Console.WriteLine("Writer {0} acquired the lock", writer); for (int i = 0; i < _items.Count; i++) { _items[i]++; Thread.Sleep(50); } Console.WriteLine("Writer {0} finished", writer); } finally { _lock.ExitWriteLock(); } } static void Main(string[] args) { var taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.None); var tasks = new Task[6]; tasks[0] = taskFactory.StartNew(WriterMethod, 1); Thread.Sleep(20); tasks[1] = taskFactory.StartNew(ReaderMethod, 1); tasks[2] = taskFactory.StartNew(ReaderMethod, 2); tasks[3] = taskFactory.StartNew(WriterMethod, 2); tasks[4] = taskFactory.StartNew(ReaderMethod, 3); tasks[5] = taskFactory.StartNew(ReaderMethod, 4); for (int i = 0; i < 6; i++) { tasks[i].Wait(); } Console.Read(); }
}
浙公网安备 33010602011771号