Новичок в программировании потоков и использовании блокировок Итак, у меня есть 2 потока - один считывает значения из COM-порта - другой управляет шаговым двигателем

В одной теме

        if stepperb_value != 0: #if stepperb non-zero
            if stepperb_value > 0: # if positive value
                self.step_fine(10,11,12,13,step_delay) #step forward
            else:
                self.step_fine(13,12,11,10,step_delay) #step backwards
            if abs(stepperb_value) != 100:
                time.sleep(10*step_delay*((100/abs(stepperb_value))-1))                       

(Мне нужно предотвратить изменение в stepperb, вызывающее ошибку деления на ноль в последней строке)

В другом потоке, который читает значения из COM-порта

            if 'stepperb' in dataraw:
                outputall_pos = dataraw.find('stepperb')
                sensor_value = dataraw[(1+outputall_pos+len('stepperb')):].split()
                print "stepperb" , sensor_value[0]
                if isNumeric(sensor_value[0]):
                    stepperb_value =  int(max(-100,min(100,int(sensor_value[0]))))

Где (и какого рода блокировки) мне нужно - первый поток чувствителен ко времени, поэтому должен иметь приоритет

С уважением

Саймон

0
SimpleSi 2 Фев 2013 в 14:47

3 ответа

Лучший ответ

Если вы используете только CPython, у вас есть другая возможность (пока).

Поскольку CPython имеет глобальную блокировку интерпретатора, назначения являются атомарными. Таким образом, вы можете вставить stepperb_value в локальную переменную вашего потока управления двигателем, прежде чем использовать ее, и использовать локальную переменную вместо глобальной.

Обратите внимание, что вы будете использовать детали реализации здесь. Возможно, ваш код не будет безопасно выполняться на других реализациях Python, таких как Jython или IronPython. Даже в CPython поведение может измениться в будущем, но я не вижу, чтобы GIL уходил до Python 5 или чего-то еще.

2
Jonas Schäfer 2 Фев 2013 в 11:14

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

2
sheu 2 Фев 2013 в 10:51

Ну, ваша критическая переменная stepperb_value, так что это то, что должно быть «защищено»:

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

http://www.laurentluce.com/posts/python-threads-synchronization-locks-rlocks-semaphores-conditions-events-and-queues/

2
Guy L 2 Фев 2013 в 11:01