Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 当一个类是线程安全和无锁的时,使用ReaderWriterLock来检测处理是否有意义?_.net_Multithreading_Dispose - Fatal编程技术网

.net 当一个类是线程安全和无锁的时,使用ReaderWriterLock来检测处理是否有意义?

.net 当一个类是线程安全和无锁的时,使用ReaderWriterLock来检测处理是否有意义?,.net,multithreading,dispose,.net,Multithreading,Dispose,假设我有一个线程安全的类,这意味着任何公共实例方法都是线程安全的。该类是“无锁”的,因为我没有在代码中显式使用任何锁。有一个ConcurrentDictionary正在使用,它使用自己的锁,但是从我自己的代码的角度来看,没有使用锁 问题是“处置”。一旦开始处理我的对象,访问ConcurrentDictionary或modifies Timer对象等对象的无锁代码将因意外异常而崩溃,例如,如果检查一个_disposed标志,看它是否为false,然后在另一个线程开始处理该对象时继续。我认为,仅仅说

假设我有一个线程安全的类,这意味着任何公共实例方法都是线程安全的。该类是“无锁”的,因为我没有在代码中显式使用任何锁。有一个ConcurrentDictionary正在使用,它使用自己的锁,但是从我自己的代码的角度来看,没有使用锁

问题是“处置”。一旦开始处理我的对象,访问ConcurrentDictionary或modifies Timer对象等对象的无锁代码将因意外异常而崩溃,例如,如果检查一个_disposed标志,看它是否为false,然后在另一个线程开始处理该对象时继续。我认为,仅仅说“除Dispose外”的每个方法都是线程安全的,这是一种逃避。我见过有人这样做

理想情况下,在使用任何公共实例方法时,不应继续处理。同样,任何公共实例方法都不应在对象被释放时或在其被释放后继续。在对象被释放后调用的任何公共方法都应该抛出一个clear ObjectDisposedException

您认为一个好的解决方案是使用ReaderWriterLock,这样Dispose就可以获得“写”锁,而所有其他方法都可以获得“读”锁吗?

这样,在正常使用下,就不会有锁争用(就像我使用正常的“lock”语句一样),因为所有方法都只是获取一个读锁,同时读锁的数量没有限制。因为它们在读锁中运行的代码是线程安全的,所以它们可以在读锁部分中并发执行。当对象被释放时,写锁将确保dispose自行运行,而不会在读锁定的部分中运行任何其他代码,反之亦然。此外,每次获取“read”锁时,它应该做的第一件事是检查“disposed”标志,如果对象已被释放,则抛出异常

我只是觉得这是一种使用读写器锁的奇怪方式,因为它保护的东西是二进制的。。。类中的所有代码要么运行不安全,要么运行安全,因为对象要么已释放,要么未释放。但这对我来说似乎很有意义。也许有更好的办法?

是的,我认为a是这里最好的选择

问题不是在处理过程中启动操作。这是最简单的部分,只需使用。最难的部分是在操作过程中不开始处理。为此,您需要您的操作在执行时获得某种锁。
ReaderWriterLockSlim
非常符合要求。

是的,我认为a是最好的选择


问题不是在处理过程中启动操作。这是最简单的部分,只需使用。最难的部分是在操作过程中不开始处理。为此,您需要您的操作在执行时获得某种锁。
ReaderWriterLockSlim
完全符合要求。

它不符合要求。只有当没有其他代码可以使用该对象时,才能调用Dispose()。这不可避免地意味着您永远不需要防止并发的锁。使用RWL只能隐藏一个bug。处置是可选的,当它变得太难做正确的时候,最好不要这样做。@HansPassant但是RWL是否真的能更容易地发现这样的错误,因为它能确保抛出一个正确的
ObjectDisposedException
,而不是由于内部处于未定义状态而导致更不可预测的事情?是的,在我看来,“Disposed”实际上是一种超状态,一个对象作为一个整体可以处于这种状态。因此,为了使对象是线程安全的和一次性的,任何实现都必须正确使用此模式。如果线程安全对象的方法可以由任何线程调用,并且对象可以由任何线程处理,那么这意味着所有方法都应该包装在这种读写器锁中。实际上,Nito.AsyncEx有一个AsyncReaderWriterLock,它返回一个可释放的锁。我将其包装在一个类中,该类处理读取获取锁,并在释放时自动抛出。。。这看起来可疑。并不是说它没有按照罐头上说的做,而是我想知道这是否是应该做的事情<代码>异步/
等待
一直都是关于异步IO的,而不是线程同步。以这种方式使用它有意义吗?我不确定。。。但我也不确定它不会。我需要考虑一下这一点。重点是,由于
async
/
await
的性质,您可能会遇到同一个线程尝试两次获取锁。此时,您不再将锁授予线程,而是授予。。。不知道该怎么称呼他们。也许是任务?不是。只有当没有其他代码可以使用该对象时,才能调用Dispose()。这不可避免地意味着您永远不需要防止并发的锁。使用RWL只能隐藏一个bug。处置是可选的,当它变得太难做正确的时候,最好不要这样做。@HansPassant但是RWL是否真的能更容易地发现这样的错误,因为它能确保抛出一个正确的
ObjectDisposedException
,而不是由于内部处于未定义状态而导致更不可预测的事情?是的,在我看来,“Disposed”实际上是一种超状态,一个对象作为一个整体可以处于这种状态。因此,为了使对象是线程安全的和一次性的,任何实现都必须正确使用此模式。如果线程安全对象的方法可以被任何线程调用,并且对象可以被任何线程处理,那么这意味着所有方法都应该被调用