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

回到顶部