如何轻松使这个计数器属性线程安全? [英] How to easy make this counter property thread safe?

查看:24
本文介绍了如何轻松使这个计数器属性线程安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在只有计数器的类中有属性定义,这必须是线程安全的,这不是因为 getset 不在同一个锁中,如何做到这一点?

I have property definition in class where i have only Counters, this must be thread-safe and this isn't because get and set is not in same lock, How to do that?

    private int _DoneCounter;
    public int DoneCounter
    {
        get
        {
            return _DoneCounter;
        }
        set
        {
            lock (sync)
            {
                _DoneCounter = value;
            }
        }
    }

推荐答案

如果您希望以DoneCounter = DoneCounter + 1 保证不受约束的方式实现该属性竞争条件,它不能在属性的实现中完成.该操作不是原子操作,它实际上分为三个不同的步骤:

If you're looking to implement the property in such a way that DoneCounter = DoneCounter + 1 is guaranteed not to be subject to race conditions, it can't be done in the property's implementation. That operation is not atomic, it actually three distinct steps:

  1. 检索 DoneCounter 的值.
  2. 加1
  3. 将结果存储在 DoneCounter 中.
  1. Retrieve the value of DoneCounter.
  2. Add 1
  3. Store the result in DoneCounter.

您必须防止在任何这些步骤之间发生上下文切换的可能性.锁定在 getter 或 setter 内无济于事,因为该锁定的范围完全存在于其中一个步骤(1 或 3)中.如果您想确保所有三个步骤一起发生而不会被中断,那么您的同步必须涵盖所有三个步骤.这意味着它必须发生在包含所有三个的上下文中.这可能最终成为不属于任何包含 DoneCounter 属性的类的代码.

You have to guard against the possibility that a context switch could happen in between any of those steps. Locking inside the getter or setter won't help, because that lock's scope exists entirely within one of the steps (either 1 or 3). If you want to make sure all three steps happen together without being interrupted, then your synchronization has to cover all three steps. Which means it has to happen in a context that contains all three of them. That's probably going to end up being code that does not belong to whatever class contains the DoneCounter property.

使用你的对象的人有责任照顾线程安全.通常,没有具有读/写字段或属性的类可以通过这种方式成为线程安全的".但是,如果您可以更改类的接口以便不需要 setter,则可以使其更加线程安全.例如,如果您知道 DoneCounter 只会递增和递减,那么您可以像这样重新实现它:

It is the responsibility of the person using your object to take care of thread safety. In general, no class that has read/write fields or properties can be made "thread-safe" in this manner. However, if you can change the class's interface so that setters aren't necessary, then it is possible to make it more thread-safe. For example, if you know that DoneCounter only increments and decrements, then you could re-implement it like so:

private int _doneCounter;
public int DoneCounter { get { return _doneCounter; } }
public int IncrementDoneCounter() { return Interlocked.Increment(ref _doneCounter); }
public int DecrementDoneCounter() { return Interlocked.Decrement(ref _doneCounter); }

这篇关于如何轻松使这个计数器属性线程安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆