【问题标题】:Best Practices Concerning Method Locking关于方法锁定的最佳实践
【发布时间】:2013-05-01 19:29:09
【问题描述】:

我有一个方法,可以同步访问 myst,一次只允许一个线程通过它。这是我当前的实现:

private Boolean m_NoNeedToProceed;
private Object m_SynchronizationObject = new Object();

public void MyMethod()
{
    lock (m_SynchronizationObject)
    {
        if (m_NoNeedToProceed)
            return;

现在我正在考虑像这样改变它:

private Boolean m_NoNeedToProceed;
private Object m_SynchronizationObject = new Object();

public void MyMethod()
{
    if (m_NoNeedToProceed)
        return;

    lock (m_SynchronizationObject)
    {

在锁定之前快速返回不是更好吗,以便调用线程可以继续而不等待前一个完成方法调用?

【问题讨论】:

  • 在哪里可以设置m_NoNeedToProceed
  • 在其他方法中。例如,当用户单击按钮或其他任何内容时。这只是有时可以设置的一个条件,以避免该方法运行。
  • @Zarathos 可以安全地假设访问bool, char, byte, sbyte, short, ushort, uint, int, float, reference type 是原子的。所以读/写布尔是安全的。
  • @I4V 是的,但不能保证它们在多核 CPU 上是“新鲜的”。你需要一个内存屏障(使用锁或易失性或 Thread.MemoryBarrier())。

标签: c# .net locking synchronized


【解决方案1】:

是不是应该在锁定之前快速返回比较好...

没有。锁不仅仅是一种互斥机制,它还是一个内存屏障1。如果没有锁,如果任何并发线程尝试修改变量2,您可能会引入数据竞争。

顺便说一句,锁在没有争用的情况下具有良好的性能,因此无论如何您都不会获得太多性能。与往常一样,不要对性能做出假设,尤其是“接近金属”。如有疑问,请测量!

...这样调用线程就可以继续进行而不用等待前一个完成方法调用了吗?

这只是意味着您持有锁的时间超过了必要的时间。一旦共享内存不再需要保护(可能比方法退出更早)就释放锁,您无需尝试人为地规避它。


1 即触发缓存一致性机制,因此所有 CPU 内核都看到“相同”的内存。

2 例如,一个线程写入变量,但该更改会在一个内核的写入缓冲区中停留一段时间,因此其他内核上的其他线程不会立即看到它。

【讨论】:

    【解决方案2】:

    是的,只要m_NoNeedToProceed 没有任何与之相关的竞争条件。

    如果方法需要很长时间才能运行,并且某些线程不需要实际访问方法的临界区。那么最好让他们早点回来,而不是得到锁。

    【讨论】:

    • 只要 m_NoNeedToProceed 被离散设置,在方法的关键部分之外并且独立于其他线程,例如,它应该没问题。我只是想确保MyMethod 中的一个线程不会切换这个布尔值,导致另一个线程在它不应该提前退出时提前退出。
    【解决方案3】:

    是的,最好在锁定之前这样做。

    制作m_NoNeedToProceed volatile

    只是一个免责声明:volatile 不会使其成为线程安全的。它只会导致检查值是否在另一个处理器中发生变化。

    【讨论】:

    • 事物本身的名称应该引起人们的关注。
    猜你喜欢
    • 2016-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多