Pre*_*k K 16 c# concurrency multithreading
我还是很困惑......当我们写下这样的东西时:
Object o = new Object();
var resource = new Dictionary<int , SomeclassReference>();
Run Code Online (Sandbox Code Playgroud)
...并且有两个代码块o在访问时锁定resource...
//Code one
lock(o)
{
// read from resource
}
//Code two
lock(o)
{
// write to resource
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我有两个线程,一个线程执行代码读取resource和另一个写入它,我想要锁定resource,当它被读取时,编写器将不得不等待(反之亦然 - 如果它正在写到,读者必须等待).锁构造能帮助我吗?......或者我应该使用别的东西?
(我Dictionary用于此示例的目的,但可以是任何东西)
我特别关注两种情况:
将lock在两个条件帮助?
Bri*_*sen 12
大多数其他答案都解决了您的代码示例,因此我将尝试在标题中回答您的问题.
锁实际上只是一个标记.拥有令牌的人可以参加舞台.因此,您锁定的对象与您尝试同步的资源没有明确的连接.只要所有读者/作者都同意相同的标记,它就可以是任何东西.
当试图锁定一个对象时(即通过调用Monitor.Enter一个对象),运行时会检查一个线程是否已经锁定了该锁.如果是这种情况,则尝试锁定的线程被挂起,否则它将获取锁定并继续执行.
当持有锁的线程退出锁定范围(即调用Monitor.Exit)时,锁被释放,任何等待的线程现在可以获得锁.
最后关于锁的几点要记住:
Monitor.Enter/Exit而不是lock关键字,请务必将调用Exit放入finally块中,以便即使在异常情况下也会释放锁定.是的,使用锁是正确的方法.您可以锁定任何对象,但正如其他答案所述,锁定资源本身可能是最简单和最安全的.
但是,您可能希望使用读/写锁对而不是单个锁,以减少并发开销.
其基本原理是,如果只有一个线程写入,但有多个线程读取,则不希望读取操作阻止其他读取操作,而只是读取块写入,反之亦然.
现在,我更像是一个java人,所以你必须改变语法并挖掘一些文档以在C#中应用它,但是rw-locks是Java中标准并发包的一部分,所以你可以这样编写:
public class ThreadSafeResource<T> implements Resource<T> {
private final Lock rlock;
private final Lock wlock;
private final Resource res;
public ThreadSafeResource(Resource<T> res) {
this.res = res;
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
this.rlock = rwl.readLock();
this.wlock = rwl.writeLock();
}
public T read() {
rlock.lock();
try { return res.read(); }
finally { rlock.unlock(); }
}
public T write(T t) {
wlock.lock();
try { return res.write(t); }
finally { wlock.unlock(); }
}
}
Run Code Online (Sandbox Code Playgroud)
如果有人能想出一个C#代码示例......