Этот поток кода Python безопасен? - PullRequest
2 голосов
/ 18 апреля 2009
import time
import threading

class test(threading.Thread):
    def __init__ (self):
      threading.Thread.__init__(self)
      self.doSkip = False
      self.count = 0

    def run(self):
      while self.count<9:
         self.work()

    def skip(self):
      self.doSkip = True

    def work(self):
      self.count+=1
      time.sleep(1)
      if(self.doSkip):
        print "skipped"
        self.doSkip = False
        return
      print self.count

t = test()
t.start()
while t.count<9:
  time.sleep(2)
  t.skip()

Ответы [ 5 ]

2 голосов
/ 18 апреля 2009

Поток безопасен каким образом? Я не вижу здесь никакой части, которую вы могли бы защитить.

Пропустить может сбросить doSkip в любое время, поэтому нет смысла его блокировать. У вас нет ресурсов, к которым можно получить доступ одновременно - поэтому ИМХО в этом коде ничего не может быть повреждено / небезопасно.

Единственная часть, которая может работать по-разному в зависимости от блокировки / подсчета, - это сколько "пропусков" вы ожидаете при каждом вызове .skip(). Если вы хотите убедиться, что каждый пропуск приводит к пропущенному вызову .work(), вы должны изменить doSkip на счетчик, который защищен блокировкой как приращения, так и сравнения / уменьшения. В настоящее время один поток может включить doSkip после проверки, но до сброса doSkip. В данном примере это не имеет значения, но в реальной ситуации (с большим количеством кода) это может иметь значение.

1 голос
/ 19 апреля 2009

Всякий раз, когда проверка булевого значения мьютекса (например, if (self.doSkip)) отделена от набора булевых переменных мьютекса, у вас, вероятно, будут проблемы с многопоточностью.

Правило заключается в том, что ваш поток будет заменен в самое неудобное время. То есть после теста и до набора. Смещение их ближе друг к другу уменьшает окно для провалов, но не устраняет их. Вам почти всегда нужен специально созданный механизм из языка или ядра, чтобы полностью закрыть это окно.

В библиотеке потоков есть семафоры, которые можно использовать для синхронизации потоков и / или создания критических разделов кода.

0 голосов
/ 20 апреля 2009

Чтобы уточнить ответ DanM, возможно, это может произойти:

  1. Тема 1: t.skip()
  2. Тема 2: if self.doSkip: print 'skipped'
  3. Тема 1: t.skip()
  4. Тема 2: self.doSkip = False
  5. и т.д.

Другими словами, в то время как вы могли бы ожидать увидеть один «пропущенный» для каждого вызова t.skip(), эта последовательность событий нарушит это.

Однако из-за ваших sleep() звонков я думаю, что эта последовательность событий на самом деле невозможна.

(если ваш компьютер не работает действительно медленно)

0 голосов
/ 18 апреля 2009

Это и будет потокобезопасным, если вы не разделяете данные между потоками.

Если другому потоку нужно читать / записывать данные в ваш класс потока, это не будет безопасным для потока, если вы не защитите данные с помощью какого-либо механизма синхронизации (например, блокировки).

0 голосов
/ 18 апреля 2009

Очевидно, что нет никакого критически важного ресурса, поэтому я бы сказал, что он потокобезопасен.

Но, как обычно, вы не можете предсказать, в каком порядке два потока будут заблокированы / запущены планировщиком.

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