Как сделать группу операций атомарной без использования блокировки - PullRequest
0 голосов
/ 05 июня 2019

У меня есть переменная state, чьи поля интереса thread-safe и хранятся fresh с использованием ReaderWriterLockSlim. Я детализировал доступ ко всем полям, так как я использую их где-то еще отдельно.

Хотя для индивидуального доступа к полям он работает нормально, мне также нужно сделать несколько операций атомарными. В этом случае мне нужны дополнительные 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
}

У меня уже есть этот потокобезопасный, а также я гарантирую, что поток читает из памяти, а не из локального кэша. Однако мне нужно сделать несколько операций атомарными.

Атомные операции

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 или есть какое-то другое облегченное решение?

1 Ответ

1 голос
/ 05 июня 2019

Для меня было бы наиболее разумно повторно использовать существующую блокировку:

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.

Примечание: почти наверняка вам не нужна блокировка чтения / записи.Блокировки чтения / записи следует использовать только в том случае, если all из следующих условий:

  • Некоторые пути кода доступны только для чтения, а другие - для чтения / записи.
  • Читателей намного больше, чем писателей.
  • Существует большое количество последовательных читателей.

Если какие-либо из них не соответствуют действительности, то lock являетсялучший выбор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...