如何在不使用锁的情况下使一组操作原子化

How to make group of operations atomic without using Lock

我有一个 state 变量,其感兴趣的字段是 thread-safe 并使用 ReaderWriterLockSlim 保持 fresh。我已经细化了对所有字段的访问,因为我在其他地方单独使用它们。

虽然对于单独访问字段它工作正常,但我还需要进行一些操作 atomic.In 这种情况下我需要额外的 lock 吗?

我有一个已经包含 thread-safe 个字段的状态变量:

internal class State {

        private ReaderWriterLockSlim lck = new ReaderWriterLockSlim();

        private bool cmd_PopUp;

        private bool cmd_Shutdown;
        private bool cmd_Delay;



        public bool CMD_PopUp {
            get {
                try {
                    this.lck.EnterReadLock();
                    return this.cmd_PopUp;
                } finally {

                    this.lck.ExitReadLock();
                }

            }
            set {
                try {
                    this.lck.EnterWriteLock();
                    this.cmd_PopUp = value;
                } finally {

                    this.lck.ExitWriteLock();
                }
            }

        }

 //same goes for the other booleans
}

我已经有了这个线程安全的,而且我确保线程从内存中读取而不是从本地读取cache.However我需要多个操作以原子方式完成。

原子操作

public async Task Run(State state)
{

     while(true)
        {
        //do i need a lock here
                        if (state.CMD_Delay) {
                            state.CMD_Delay = false;
                            state.CMD_PopUp = false;
        //end of potential lock ?
                        } else if (state.CMD_Shutdown) { //same here
                            state.CMD_PopUp = false;
                            state.CMD_Shutdown = false;
                            await SomeAction();
                        }
        }
}

正如你在我的 while 中看到的那样,我有一个 if-else,我需要一组操作是原子的。我应该使用额外的 lock 还是有一些其他的轻量级解决方案 ?

re-use 你现有的锁对我来说最有意义:

internal class State
{
  ...
  public void SetDelayState()
  {
    try {
      this.lck.EnterWriteLock();
      this.cmd_Delay = false;
      this.cmd_PopUp = false;
    } finally {
      this.lck.ExitWriteLock();
    }
  }
  public void SetShutdownState()
  {
    try {
      this.lck.EnterWriteLock();
      this.cmd_PopUp = false;
      this.cmd_Shutdown = false;
    } finally {
      this.lck.ExitWriteLock();
    }
  }
}

换句话说,将所有原子操作移动到您的 State 类型的成员。

旁注:您几乎肯定不需要 reader/writer 锁。 Reader/writer 仅当满足以下 所有 条件时才应使用锁:

  • 部分代码路径为 read-only,其他为 read/write。
  • 读者远远多于作者。
  • 连续阅读人数较多

如果 任何 不正确,那么 lock 是更好的选择。