Многопоточный доступ ресурса - куда я помещаю свои блокировки?

Вы столкнулись с известной проблемой о том, что текущая реализация данных привязки Event Hub пропустила некоторые свойства, такие как идентификатор устройства, который вы ищете.

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

blockquote>

А вот поток , отслеживающий решение проблемы.

5
задан Corey Goldberg 15 January 2009 в 19:09
поделиться

7 ответов

Создайте блокировку вне метода.

class Agent(Thread):
    mylock = Lock()
    def write_result(self):
        self.mylock.acquire()
        try:
            ...
        finally:
            self.mylock.release()

или при использовании Python> = 2.5:

class Agent(Thread):
    mylock = Lock()
    def write_result(self):
        with self.mylock:
            ...

Для использования этого с python 2.5, необходимо импортировать оператор из будущего:

from __future__ import with_statement
3
ответ дан 18 December 2019 в 14:52
поделиться

Для Вашего варианта использования один подход мог быть должен записать a file подкласс, который блокирует:

class LockedWrite(file):
    """ Wrapper class to a file object that locks writes """
    def __init__(self, *args, **kwds):
        super(LockedWrite, self).__init__(*args, **kwds)
        self._lock = Lock()

    def write(self, *args, **kwds):
        self._lock.acquire()
        try:
            super(LockedWrite, self).write(*args, **kwds)
        finally:
            self._lock.release()

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

def main():
    f = LockedWrite('foo.txt', 'a')

    for i in range(20):
        agent = Agent(i, f)
        agent.start()

class Agent(Thread):
    def __init__(self, thread_num, fileobj):
        Thread.__init__(self)
        self.thread_num = thread_num
        self._file = fileobj    

#   ...

    def write_result(self):
        self._file.write('hello from thread %s\n' % self.thread_num)

Этот подход помещает захват файла в сам файл, который кажется инструментом для очистки, по моему скромному мнению,

6
ответ дан 18 December 2019 в 14:52
поделиться

Блокировка () метод возвращает объект блокирования для каждого вызова. Таким образом, каждый поток (на самом деле каждый вызов к write_result) будет иметь различный объект блокирования. И не будет никакой блокировки.

1
ответ дан 18 December 2019 в 14:52
поделиться

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

1
ответ дан 18 December 2019 в 14:52
поделиться

Можно упростить вещи немного (за счет немного больше служебного) путем называния единственного потока (вероятно, созданным исключительно с этой целью) как единственный поток, который пишет в файл, и имейте всего другого делегата потоков в устройстве записи файла путем размещения строки, которую они хотят добавить к файлу в a queue.Queue объект.

У очередей есть вся встроенная блокировка, таким образом, любой поток может безопасно звонить Queue.put() в любое время. Устройство записи файла было бы единственным вызовом потока Queue.get(), и может, по-видимому, провести большую часть его времени, блокируясь на том вызове (с разумным тайм-аутом, чтобы позволить потоку чисто отвечать на запрос завершения работы). Все проблемы синхронизации будут обработаны Очередью, и Вы будете сэкономлены, имея необходимость волноваться о том, забыли ли Вы, что некоторая блокировка получает/выпускает где-нибудь... :)

1
ответ дан 18 December 2019 в 14:52
поделиться

Я вполне уверен, что блокировка должна быть тем же объектом для каждого потока. Попробуйте это:

import time
from threading import Thread, Lock

def main():
    lock = Lock()
    for i in range(20):
        agent = Agent(i, lock)
        agent.start()

class Agent(Thread, Lock):
    def __init__(self, thread_num, lock):
        Thread.__init__(self)
        self.thread_num = thread_num
        self.lock = lock

    def run(self):
        while True:
            print 'hello from thread %s' % self.thread_num
            self.write_result()   

    def write_result(self):
        self.lock.acquire()
        try:
            f = open('foo.txt', 'a')
            f.write('hello from thread %s\n' % self.thread_num)
            f.flush()
            f.close()
        finally:
            lock.release()

if __name__ == '__main__':
    main()
0
ответ дан 18 December 2019 в 14:52
поделиться

Экземпляр блокировки должен быть связан с экземпляром файла.

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

1
ответ дан 18 December 2019 в 14:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: