C#ReaderWriterLockSlim [操作系统入门]
ReaderWriterLockSlim-多线程读单线程写
注意事项
(1)线程A如果通过EnterReadLock获取到读锁(ReadLock)后,不能在持有读锁的情况下再申请获取写锁(WriteLock)
如果违反了这个规定就报如下错:
Write lock may not be acquired with read lock held. This pattern is prone to deadlocks. Please ensure that read locks are released before taking a write lock. If an upgrade is necessary, use an upgrade lock in place of the read lock.
(2)线程A如果通过EnterReadLock获取到读锁(ReadLock)后,不能在持有读锁的情况下再申请获取可升级读锁(UpgradeableReadLock)
如果违反了这个规定就报如下错:
Upgradeable lock may not be acquired with read lock held
(3)线程A如果通过EnterUpgradeableReadLock获取到可升级读锁(UpgradeableReadLockk)后,可以再持有可升级读锁的情况通过EnterWriteLock获取写锁
递归锁
递归锁:同一个线程获取到该锁后可以再获取该锁多次,不会产生死锁。
使用默认构造函数构造的ReaderWriterLockSlim是不允许锁递归的,如果一个线程已经获取到该锁后又获取该锁就会出错,如报错“Recursive upgradeable lock acquisitions not allowed in this mode”
示例如下:
解决方法:使用允许递归锁的构造方法(即new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion))构造ReaderWriterLockSlim实例
如何判断代码逻辑里会触发递归锁呢,抓住两个要点“同一线程(即ManageThreadId一样)”和“同一个锁”,在线程池里运行的时候,由于可以重用工作线程,很容易触发递归锁的问题,比如这样:线程池线程1获取到UpgradeableReadLock锁后由于后面代码里有长时等待任务,调度器可能调度线程1运行队列里的另一个同样代码的任务,这时由于代码一样线程1再次申请获取UpgradeableReadLock锁(因为上一次他已经获取到该UpgradeableReadLock锁了),就会报错了
示例代码:
staticvoid Main(){
ReaderWriterLockSlimTest();
Console.Read();
}
publicstaticvoid ReaderWriterLockSlimTest(){
Console.WriteLine($
"主线程Id : {Thread.CurrentThread.ManagedThreadId}");// 定义共享资源var list = new List<string>();
// 定义ReaderWriterLockSlim共享实例
//ReaderWriterLockSlim readerWriterLockSlim = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); // 允许递归锁
ReaderWriterLockSlim readerWriterLockSlim = new ReaderWriterLockSlim();
//TaskMethod0102("task1", 1, list, readerWriterLockSlim);
var task1 = Task.Run(() => TaskMethod0102("task1", 1, list, readerWriterLockSlim));
var task2 = Task.Run(() => TaskMethod0102("task2", 2, list, readerWriterLockSlim));
var task3 = Task.Run(() => TaskMethod0102("task3", 3, list, readerWriterLockSlim));
//var thread1 = new Thread(() => TaskMethod0102("task1", 1, list, readerWriterLockSlim));
//var thread2 = new Thread(() => TaskMethod0102("task2", 1, list, readerWriterLockSlim));
//var thread3 = new Thread(() => TaskMethod0102("task3", 1, list, readerWriterLockSlim));
}
publicstaticstring TaskMethod0102(string taskName,double seconds,List<string> list,ReaderWriterLockSlim readerWriterLockSlim)
{
try
{
Console.WriteLine($"{taskName} want to Read ,线程Id:{Thread.CurrentThread.ManagedThreadId}");
//readerWriterLockSlim.EnterReadLock(); // 尝试获取读锁
readerWriterLockSlim.EnterUpgradeableReadLock(); // 尝试获取可升级读锁
Console.WriteLine($"{taskName} success to Read ,集合总数:{(list == null ? 0 : list.Count)} ,线程Id:{Thread.CurrentThread.ManagedThreadId}");
Console.WriteLine($"{taskName} want to Write ,线程Id:{Thread.CurrentThread.ManagedThreadId}");
readerWriterLockSlim.EnterWriteLock();
Console.WriteLine($"{taskName} success to Write ,线程Id:{Thread.CurrentThread.ManagedThreadId}");
list.Add(taskName);
return"OK";
}
catch(Exception ex)
{
return"发生异常,异常信息:" + ex.Message;
}
finally
{
Console.WriteLine($"{taskName } 释放所有的锁 ,线程Id:{Thread.CurrentThread.ManagedThreadId}");
readerWriterLockSlim.ExitUpgradeableReadLock();
readerWriterLockSlim.ExitWriteLock();
}
}
运行结果:
C# ReaderWriterLockSlim
以上是 C#ReaderWriterLockSlim [操作系统入门] 的全部内容, 来源链接: utcz.com/z/519458.html