Являются ли переменные экземпляра Python потокобезопасными? - PullRequest
19 голосов
/ 29 ноября 2011

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

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(), чтобы заблокировать этот ресурс, лучше?

Ответы [ 4 ]

32 голосов
/ 29 ноября 2011

Вы можете использовать Замки, Замки, Семафоры, Условия, События и Очереди.
И эта статья помогла мне много .
Проверьте это: Блог Лорана Люса

23 голосов
/ 29 ноября 2011

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

Поэтому вам необходимо защититьвся операция с блокировкой.

Поскольку тело метода - это в основном вся операция, вы можете использовать для этого декоратор.Смотрите этот ответ для примера: https://stackoverflow.com/a/490090/34088

9 голосов
/ 29 ноября 2011

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

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

1 голос
/ 05 сентября 2012

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

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

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