线程同步 - 线程锁
线程锁的原理:锁住一个资源,使得应用程序在同一时刻只有一个线程访问该资源。
通俗地讲,就是让多线程变成单线程。
需要锁定的资源就是 C# 中的一个对象。在选择锁对象(同步对象)时,应当始终注意以下几点:
同步对象在需要同步的多个线程中是可见的同一个对象;
在非静态方法中,静态变量不应作为同步对象;
值类型对象不能作为同步对象;
避免将字符串作为同步对象;
降低同步对象的可见性;
编写多线程代码时,要遵循下面的一个原则:类型的静态方法应当保证线程安全性,非静态方法不需要实现线程安全
示例代码
cs
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;
namespace WaitHandleSample
{
public partial class LockSample : Form
{
AutoResetEvent autoSet = new AutoResetEvent(false);
List<string> tempList = new List<string>() { "init0", "init1", "init2" };
public LockSample()
{
InitializeComponent();
}
private void btnStartThreads_Click(object sender, EventArgs e)
{
object syncObj = new object();
Thread t1 = new Thread(() =>
{
// 确保等待 t2 开始之后才运行下面的代码
autoSet.WaitOne();
lock(syncObj)
{
foreach (var item in tempList)
{
Thread.Sleep(1000);
}
}
});
t1.IsBackground = true;
t1.Start();
Thread t2 = new Thread(() =>
{
// 通知 t1 可以执行代码
autoSet.Set();
// 沉睡一秒是为了确保删除操作在 t1 的迭代过程中
Thread.Sleep(1000);
lock (syncObj)
{
tempList.RemoveAt(1);
}
});
t2.IsBackground = true;
t2.Start();
}
}
}
上面的代码可以正常执行结束;删除掉 lock
语句后执行,会抛出如下异常:
集合已修改;可能无法执行枚举操作。