2011-01-07 3 views
13

Есть ли аннотация, связанная с блокировкой на основе python, которая имеет такой же эффект для метода python, что и «синхронизированное» ключевое слово для java-методов?аннотация метода блокировки python

+0

спасибо за комментарий, не можете ли вы уточнить? – paweloque

+3

Это зависит от того, что вы делаете. Python имеет «глобальную блокировку интерпретатора», поэтому только один поток может выполнять код Python за раз, и вы не можете использовать несколько ядер. Но если ваш код ожидает доступа к диску или данных из сети или вычисления numpy, многопоточность работает. –

+0

Ксавье, не извергайте ерунду. Многопоточность - это не всегда плохая идея.Конечно, у него есть проблемы с его GIL на многоядерных системах для некоторого кода с привязкой к ЦП ... но этого недостаточно, чтобы назвать все это «плохой идеей». –

ответ

15

я могу предположить, что никакая встроенная функция не существует в Python, но вы можете реализовать его понимание того, как это работает на Java от this ссылки:

Каждого Java объект, созданного, в том числе нагруженных каждый класс имеет связанный с ним блокировка или монитор. Размещение кода внутри синхронизированного блока делает инструкцию Append компилятора приобрести замок на указанном объекте до того выполнения кода, и освободить его впоследствии (либо потому, что код заканчивается нормально или ненормально). Между приобретением замка и , выпуская его, резьба называется «собственный» замок. В точке Thread Требуется приобрести замок, если Резьба B уже принадлежит ему, то Резьба A должна дождаться, когда Thread B до освободит его.

поэтому, возможно, что-то подобное может работать:

синхронизируется заявление в Java:

public class Java { 
    static private int count = 0; 

    public void increment() { 
     synchronized (this) { 
      count++; 
     } 
    } 
} 

стали:

import threading 

class Java: 
    cout = 0 
    lock = threading.RLock() 

    def increment(): 
     with Java.lock: 
      Java.cout += 1 

и синхронизированные методы в Java:

public class Java { 
    static private int count = 0; 

    public synchronized void increment() { 
     count ++; 
    } 
} 

стали:

import threading 

def synchronized(method): 
    """ Work with instance method only !!! """ 

    def new_method(self, *arg, **kws): 
     with self.lock: 
      return method(self, *arg, **kws) 


    return new_method 

class Java: 
    count = 0 
    lock = threading.RLock() 

    @synchronized 
    def incremenet(self): 
     Java.count += 1 

Явное лучше, чем неявное.

N.B: мои знания в Java очень ограничены, и это моя первая лекция об этой Java-функции, поэтому, возможно, я что-то пропустил (или, может быть, я пропустил всю точку здесь :)), надеюсь, что этот ответ может кому-то помочь.

NB: блокировка, которую я создал, представляет собой переменную класса, поэтому синхронизация потоков выполняется на уровне класса, если мы хотим сделать синхронизацию на уровне экземпляра (только), которая, как мне кажется, соответствует тому, что делает java, код выше должен изменение.

+3

Вы также можете использовать 'with lock:' вместо методов получения и выпуска. –

+0

@Thomas K: спасибо за замечание :) обновлено – mouad

+1

Возможно, вы захотите добавить 'return' в свой декоратор: это не нужно для вашего примера, но оно позволяет повторно использовать декоратор с помощью метода, который возвращает что-то. Также нет особых причин для явного доступа к блокировке через класс, если вы не назначаете его, вы можете получить доступ к переменной класса через экземпляр. 'с self.lock: метод возврата (self, * args, ** kws)' – Duncan

1

Я иногда использую декоратора, как это:

def synchronized(f): 
    @functools.wraps(f) 
    def wrapper(self, *args, **kwargs): 
     try: 
      _ = self._lock 
     except AttributeError: 
      self._lock = threading.Lock() 

     with self._lock: 
      return f(self, *args, **kwargs) 
    return wrapper 

Это решение имеет состояние гонки при вызове метода декорированный в первый раз, хотя. Самый простой способ избежать этой проблемы - вызвать один синхронизированный метод, когда ни один другой поток не запущен первым, или назначить self._lock вручную в __init__

Смежные вопросы