前言
在编程的时候,有时会使用多线程来解决问题,比如你的程序需要在后台处理一大堆数据,但还要使用户界面处于可操作状态;或者你的程序需要访问一些外部资源如数据库或网络文件等。这些情况你都可以创建一个子线程去处理,然而,多线程不可避免地会带来一个问题,就是线程同步的问题,即要通过线程同步编写出安全且高效的多线程的多线程程序。
一、线程安全与锁
线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时对一个变量执行读写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
二、实例介绍
1、lock锁机制
public class Program
{
private object locker = new object();
int num = 1;
public static void Main(string[] args)
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();//开始计时
Program program = new Program();
ThreadStart threadStart = new ThreadStart(program.Run);//Run--对象引用对非静态的方法Run,使用program.Run是必要的
for (int i = 0; i < 5; i++)
{
Thread thread = new Thread(threadStart);
thread.Start();
}
program.num++;
Console.WriteLine("num is:" + program.num);
Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
//停止计时
stopWatch.Stop();
//输出执行的时间,毫秒数
Console.WriteLine("The execution time is " + stopWatch.ElapsedMilliseconds + " milliseconds.");
Console.ReadKey();
}
public void Run()
{
lock (locker)
{
num++;
Console.WriteLine("num is:" + num);
Console.WriteLine("Child thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
}
}
执行结果:
lock 是一种比较好用的简单的线程同步方式,它是通过为给定对象获取互斥锁来实现同步的。可以看到这种方式的确没有阻塞主线程,而且成员变量的值也是连续递增的,说明是线程安全的。lock 锁机制表示在同一时刻只有一个线程可以锁定同步对象(在这里是locker),任何竞争的的其它线程都将被阻止,直到这个锁被释放。
lock 的参数必须是基于引用类型的对象,不要是基本类型,比如 bool、int,这样根本不能同步,原因是lock的参数要求是对象,如果传入 int,势必要发生装箱操作,这样每次lock的都将是一个新的不同的对象。最好避免使用public类型或不受程序控制的对象实例,因为这样很可能导致死锁。永远也不要 lock 一个字符串。
应该注意以下几点:
1)如果一个类的实例是public的,最好不要lock(this)。因为使用你的类的人也许不知道你用了lock,如果他new了一个实例,并且对这个实例上锁,就很容易造成死锁。
2)如果MyType是public的类型,不要lock(typeof(MyType))
3)永远也不要lock一个字符串
2、其它的几种同步方法
Monitor类、Mutex类、同步事件和等待句柄
以后抽时间再写
参考文章:
https://www.cnblogs.com/Brambling/p/7174597.html
http://www.cnblogs.com/yank/p/3227324.html
http://www.cnblogs.com/SkySoot/archive/2012/04/02/2430295.html