Подтвердить что ты не робот

Являются ли переменные экземпляра Python безопасными для потоков?

ОК, сначала проверьте следующие коды:

class DemoClass():

    def __init__(self):
        #### I really want to know if self.Counter is thread-safe. 
        self.Counter = 0

    def Increase(self):
        self.Counter = self.Counter + 1

    def Decrease(self):
        self.Counter = self.Counter - 1

    def DoThis(self):
        while True:
            Do something

            if A happens:
                self.Increase()
            else:
                self.Decrease()

            time.sleep(randomSecs)

    def DoThat(self):
        while True:
            Do other things

            if B happens:
                self.Increase()
            else:
                self.Decrease()

            time.sleep(randomSecs)

    def ThreadSafeOrNot(self):
        InterestingThreadA = threading.Thread(target = self.DoThis, args = ())
        InterestingThreadA.start()

        InterestingThreadB = threading.Thread(target = self.DoThat, args = ())
        InterestingThreadB.start()

Я столкнулся с такой же ситуацией, как и выше. Я действительно хочу знать, является ли это потокобезопасным для self.Counter, ну, если нет, какие у меня есть варианты? Я могу только думать о threading.RLock(), чтобы заблокировать этот ресурс, любую лучшую идею?

4b9b3361

Ответ 1

Вы можете использовать Locks, RLocks, Semaphores, Conditions, Events и Queues.
И эта статья помогла мне много.
Проверьте это: Блог Laurent Luce

Ответ 2

Использование поля экземпляра self.Counter потокобезопасного или "атомарного" . Чтение или назначение одного значения - даже если ему требуется 4 байта в памяти, вы никогда не получите половину измененного значения. Но операция self.Counter = self.Counter + 1 заключается не только в том, что она считывает значение, а затем записывает его - другой поток может изменить значение поля после его чтения и перед его записью.

Итак, вам нужно защитить всю операцию с помощью блокировки.

Так как тело метода - это в основном вся операция, вы можете использовать декоратор для этого. См. Этот ответ для примера: fooobar.com/questions/25284/...

Ответ 3

Нет, он не является потокобезопасным - два потока существенно изменяют одну и ту же переменную одновременно. И да, решение является одним из механизмов блокировки в модуле threading.

BTW, self.Counter - это переменная экземпляра, а не переменная класса.

Ответ 4

self.Counter является переменной экземпляра, поэтому у каждого потока есть копия.

Если вы объявите переменную вне __init__(), это будет переменная класса. Все экземпляры класса будут использовать этот экземпляр.