多个线程对同一资源的争夺,有可能出现线程不安全的现象。用lock
这种最简单的方式实现下。
直观的看下这种情况:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; using System.Threading; namespace ThreadSafetyDemo { class Program { [STAThread] static void Main() { Thread.CurrentThread.Name = "====主线程===="; Program prg = new Program(); Thread newThread = new Thread(new ThreadStart(prg.DoSomeWork)); newThread.Name = "**新线程:"; newThread.IsBackground = true; newThread.Start(); // 开始新线程 prg.DoSomeWork(); // 开始主线程 Console.ReadKey(); } // 放在外面作为成员变量,这样连个线程操纵的时候才能看出不一样。 private int counter = 0; private void DoSomeWork() { for (int i = 1; i < 11; i++) { counter += i; Console.WriteLine("{0}{1}", Thread.CurrentThread.Name, counter); } } } }
输出:
====主线程====1 ====主线程====4 ====主线程====7 ====主线程====11 ====主线程====16 ====主线程====22 ====主线程====29 **新线程:2 **新线程:39 **新线程:42 **新线程:46 **新线程:51 **新线程:57 **新线程:64 **新线程:72 **新线程:81 **新线程:91 ====主线程====37 ====主线程====100 ====主线程====110
每次的结果其实都不一样,这就是线程的不安全,多个线程操纵了同意资源。
保证线程安全,加一个lock
块。
private void DoSomeWork() { lock (this) { for (int i = 1; i < 11; i++) { counter += i; Console.WriteLine("{0}{1}", Thread.CurrentThread.Name, counter); } } }
这样就没问题,保证只有一个线程调用。
更优雅的方式写法:
增加命名空间using System.Runtime.CompilerServices;
。然后在函数前增加一个这样的标签就可以——[MethodImpl(MethodImplOptions.Synchronized)]
。
[MethodImpl(MethodImplOptions.Synchronized)] private void DoSomeWork() { for (int i = 1; i < 11; i++) { counter += i; Console.WriteLine("{0}{1}", Thread.CurrentThread.Name, counter); } }
这样子也可以,也是同样的效果。