C# 使用Monitor类、lock和Mutex类进行多线程同步
- 在多线程中,为了使数据保持一致性必须要对数据或是访问数据的函数加锁,在数据库中这是很常见的,但是在程序中大部分都是单线程的程序,所以没有加锁的必要,但是在多线程中,为了保持数据的同步,一定要加锁。
- 在Framework中已经为我们提供了三个加锁的机制,分别是Monitor类、lock关键字和Mutex类。
- Monitor和lock用法差不多,都是锁定数据或是锁定被调用的函数。Mutex多用于锁定多线程间的同步调用。
- Mutex只能互斥线程间的调用,但是不能互斥本线程的重复调用。运行下面程序,可以看出thread1中waitOne()只对thread2中的waitOne()起到互斥的作用,但是thread1并不受waitOne()的影响,可以调用多次,只是在调用结束后调用相同次数的ReleaseMutex()就可以。
private void thread1Func()
{
for (int count = 0; count < 10; count++)
{
mutex.WaitOne();
TestFunc("Thread1 have run " + count.ToString() + " times");
mutex.ReleaseMutex();
}
}
private void thread2Func()
{
for (int count = 0; count < 10; count++)
{
mutex.WaitOne();
TestFunc("Thread2 have run " + count.ToString() + " times");
mutex.ReleaseMutex();
}
}
private void TestFunc(string str)
{
Console.WriteLine("{0} {1}", str, System.DateTime.Now.Millisecond.ToString());
Thread.Sleep(50);
}
- 那么如何使线程按照调用顺序来依次执行呢?其实把lock和Mutex结合起来使用就可以了。
private void thread1Func()
{
for (int count = 0; count < 10; count++)
{
lock (this)
{
mutex.WaitOne();
TestFunc("Thread1 have run " + count.ToString() + " times");
mutex.ReleaseMutex();
}
}
}
private void thread2Func()
{
for (int count = 0; count < 10; count++)
{
lock (this)
{
mutex.WaitOne();
TestFunc("Thread2 have run " + count.ToString() + " times");
mutex.ReleaseMutex();
}
}
}
C# 多线程 Mutex(互斥锁)
- 互斥锁
a. 互斥锁是一个互斥的同步对象,意味着同一时间有且仅有一个线程可以获取它。
b. 互斥锁可适用于一个共享资源每次只能被一个线程访问的情况。
ConcurrentDictionary<TKey, TValue> 类
表示可由多个线程同时访问的键/值对的线程安全集合。
任务 | 方法 | 用法说明 |
---|---|---|
添加的Key值在字典内不存在 | TryAdd | 如果当前不在字典中存在该键,此方法见刚添加制定键/值对。改方法返回true或false具体取决于是否已添加新对。 |
如果改注册表项具有特定值,更新为现有键在字典中值 | TryUpdate | 此方法检查是否Key具有指定的值,如果它存在,则用新值更新该键。 |
无条件地将键/值对存储在字典中,覆盖已存在的键的值 | dictionary[key]=newValue | |
将键/值对添加到字典中,或如果Key已存在,更新基于键的现有值的键的值 | AddOrUpdate | AddOrUpdate(TKey, Func, Func) 接受的键和两个委托。 如果键在字典; 中不存在,则使用第一个委托它接受键并返回应添加的键的值。 如果该键不存在; 它使用第二个委托它接受的键和其当前值,并返回应为项设置的新值。AddOrUpdate(TKey, TValue, Func) 接受键、 值要添加,以及更新委托。 这是与以前的重载中,相同之处在于它不使用委托来添加的键。 |
获取此键在字典中,向字典中添加值并将其返回如果该键不存在的值 | GetOrAdd | 这些重载提供延迟初始化为键/值对在字典中,添加的值,仅当不存在。GetOrAdd(TKey, TValue) 采用键不存在要添加的值。GetOrAdd(TKey, Func) 将一个委托,可将生成的值,如果键不存在。 |