Rob*_*Day 5 c# multithreading locking thread-safety
我正在尝试使用ReaderWriterLockSlim该类来管理列表.
这个列表有很多读取,写入很少,我的读取很快,而我的写入很慢.
我有一个简单的测试工具来检查锁的工作原理.
如果发生以下情况
Thread 1 - Start Write
Thread 2 - Start Read
Thread 3 - Start Write
Run Code Online (Sandbox Code Playgroud)
然后结果如下
Thread 1 starts its write and locks the list.
Thread 2 adds itself to the read queue.
Thread 3 adds itself to the write queue.
Thread 1 finishes writing and releases the lock
Thread 3 aquires the lock and starts its write
Thread 3 finishes writing and releases the lock
Thread 2 performs its read
Run Code Online (Sandbox Code Playgroud)
是否有任何方法可以更改锁的行为,以便在授予写锁之前允许在写锁之前排队的任何读取请求完成?
编辑:演示我的问题的代码如下
public partial class SimpleLock : System.Web.UI.Page
{
public static ReaderWriterLockSlim threadLock = new ReaderWriterLockSlim();
protected void Page_Load(object sender, EventArgs e)
{
List<String> outputList = new List<String>();
Thread thread1 = new Thread(
delegate(object output)
{
((List<String>)output).Add("Write 1 Enter");
threadLock.EnterWriteLock();
((List<String>)output).Add("Write 1 Begin");
Thread.Sleep(100);
((List<String>)output).Add("Write 1 End");
threadLock.ExitWriteLock();
((List<String>)output).Add("Write 1 Exit");
}
);
thread1.Start(outputList);
Thread.Sleep(10);
Thread thread2 = new Thread(
delegate(object output)
{
((List<String>)output).Add("Read 2 Enter");
threadLock.EnterReadLock();
((List<String>)output).Add("Read 2 Begin");
Thread.Sleep(100);
((List<String>)output).Add("Read 2 End");
threadLock.ExitReadLock();
((List<String>)output).Add("Read 2 Exit");
}
);
thread2.Start(outputList);
Thread.Sleep(10);
Thread thread3 = new Thread(
delegate(object output)
{
((List<String>)output).Add("Write 3 Enter");
threadLock.EnterWriteLock();
((List<String>)output).Add("Write 3 Begin");
Thread.Sleep(100);
((List<String>)output).Add("Write 3 End");
threadLock.ExitWriteLock();
((List<String>)output).Add("Write 3 Exit");
}
);
thread3.Start(outputList);
thread1.Join();
thread2.Join();
thread3.Join();
Response.Write(String.Join("<br />", outputList.ToArray()));
}
}
Run Code Online (Sandbox Code Playgroud)
是否有任何方法可以更改锁的行为,以便允许在授予写锁之前完成在写锁之前排队的任何读取请求?
几乎完全避免使用锁怎么样?在写入期间,您可以获取锁、复制原始数据结构、修改副本,然后通过用新引用替换旧引用来发布新数据结构。由于在“发布”数据结构后您永远不会修改数据结构,因此您根本不需要锁定读取。
下面是它的工作原理:
public class Example
{
private object writelock = new object();
private volatile List<string> data = new List<string>();
public void Write(string item)
{
lock (writelock)
{
var copy = new List<string>(data); // Create the copy.
copy.Add(item); // Modify the data structure.
data = copy; // Publish the modified data structure.
}
}
public string Read(int index)
{
return data[index];
}
}
Run Code Online (Sandbox Code Playgroud)
我们在这里利用的技巧是变量引用的任何内容的不变性data。我们唯一需要做的就是将变量标记为volatile。
请注意,只有当写入频率足够低并且数据结构足够小以保持复制操作便宜时,此技巧才有效。这不是万能的解决方案。它并不适合所有场景,但它可能适合您。