线程与并发系列一:Lock、Monitor、UserSpinLock
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; namespace MyConsole.ThreadDemo { class Lock { static int Storeage { get; set; } static object LockObject = new object(); static void Main(string[] args) { var timer = new Stopwatch(); var my = new Lock(); var data = new Dictionary<string, Action>() { {"错误的代码",my.Wrong}, {"正解的代码 使用Lock",my.UserLock}, {"正解的代码 使用Monitor",my.UserMonitor}, {"使用UserSpinLock",my.UserSpinLock}, }; foreach (var item in data) { Console.WriteLine(); Console.WriteLine(item.Key); timer.Restart(); my.Being(new ThreadStart(item.Value)); timer.Stop(); Console.WriteLine(timer.ElapsedTicks); } } #region = Wrong = void Wrong() { var random = new Random(DateTime.Now.Millisecond); var w = random.Next(100); Lock.Storeage = w; Thread.Sleep(random.Next(1, 5)); var r = Lock.Storeage; Message(w, r); } #endregion #region = UserLock = void UserLock() { var random = new Random(DateTime.Now.Millisecond); var w = random.Next(100); var r = -1; lock (LockObject) { Lock.Storeage = w; Thread.Sleep(random.Next(100, 500)); r = Lock.Storeage; } Message(w, r); } #endregion #region = UserMonitor = void UserMonitor() { var random = new Random(DateTime.Now.Millisecond); var w = random.Next(100); var r = -1; Monitor.Enter(LockObject); Lock.Storeage = w; Thread.Sleep(random.Next(100, 500)); r = Lock.Storeage; Monitor.Exit(LockObject); Message(w, r); } #endregion #region = UserSpinLock = SpinLock _spinlock = new SpinLock(); void UserSpinLock() { var random = new Random(DateTime.Now.Millisecond); var w = random.Next(100); var r = -1; var lockTaken = false; _spinlock.Enter(ref lockTaken); Lock.Storeage = w; Thread.Sleep(random.Next(100, 500)); r = Lock.Storeage; _spinlock.Exit(); Message(w, r); } #endregion #region = Being = void Being(ThreadStart start) { var threads = Enumerable.Range(0, 10).Select(x => new Thread(start)).ToList();//必须ToList一下 foreach (var item in threads) { item.Start(); } foreach (var item in threads) { item.Join(); } } #endregion #region - Message - static void Message(int w, int r) { var msg = string.Format("线程{0}在运行 存入{1} 读出{2} {3}", Thread.CurrentThread.ManagedThreadId, r, w, r == w ? "正确" : "错误"); Console.WriteLine(msg); } #endregion } }
输出
错误的代码 线程5在运行 存入99 读出95 错误 线程4在运行 存入99 读出95 错误 线程6在运行 存入99 读出47 错误 线程3在运行 存入99 读出43 错误 线程8在运行 存入99 读出47 错误 线程7在运行 存入99 读出47 错误 线程9在运行 存入99 读出47 错误 线程10在运行 存入99 读出47 错误 线程12在运行 存入99 读出99 正确 线程11在运行 存入99 读出99 正确 31323 正解的代码 使用Lock 线程13在运行 存入8 读出8 正确 线程14在运行 存入61 读出61 正确 线程16在运行 存入61 读出61 正确 线程15在运行 存入61 读出61 正确 线程18在运行 存入65 读出65 正确 线程17在运行 存入13 读出13 正确 线程20在运行 存入17 读出17 正确 线程19在运行 存入65 读出65 正确 线程22在运行 存入22 读出22 正确 线程21在运行 存入70 读出70 正确 6118886 正解的代码 使用Monitor 线程23在运行 存入90 读出90 正确 线程25在运行 存入90 读出90 正确 线程24在运行 存入90 读出90 正确 线程27在运行 存入95 读出95 正确 线程26在运行 存入95 读出95 正确 线程29在运行 存入56 读出56 正确 线程31在运行 存入65 读出65 正确 线程28在运行 存入52 读出52 正确 线程30在运行 存入61 读出61 正确 线程32在运行 存入70 读出70 正确 6346075 使用UserSpinLock 线程33在运行 存入19 读出19 正确 线程40在运行 存入24 读出24 正确 线程41在运行 存入76 读出76 正确 线程35在运行 存入71 读出71 正确 线程34在运行 存入19 读出19 正确 线程38在运行 存入24 读出24 正确 线程39在运行 存入24 读出24 正确 线程36在运行 存入71 读出71 正确 线程37在运行 存入24 读出24 正确 线程42在运行 存入76 读出76 正确 6018558