Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python lock method annotation

Is there a python lock annotation which has the same effect to a python method as the "synchronized" keyword to java methods?

like image 724
paweloque Avatar asked Jan 07 '11 11:01

paweloque


People also ask

What does lock () do in Python?

A lock can be locked using the acquire() method. Once a thread has acquired the lock, all subsequent attempts to acquire the lock are blocked until it is released. The lock can be released using the release() method. Calling the release() method on a lock, in an unlocked state, results in an error.

What is mutex in Python?

A mutex is an object enabling threads of execution to protect critical sections of code from reentrancy or to temporarily protect critical data sets from being updated by other threads. The term “mutex” derives from the notion of mutual exclusion.

What is lock acquire?

Acquiring a lock allows a thread to have exclusive access to the data guarded by that lock, forcing other threads to block — as long as those threads are also trying to acquire that same lock. The monitor pattern guards the rep of a datatype with a single lock that is acquired by every method.

How do you make a method synchronized in Python?

The threading module provided with Python includes a simple-to-implement locking mechanism that allows you to synchronize threads. A new lock is created by calling the Lock() method, which returns the new lock. The acquire(blocking) method of the new lock object is used to force threads to run synchronously.


2 Answers

I can assume that no builtin feature exist in python but you can implement it by understanding how it work in Java from this link :

Every Java object created, including every Class loaded, has an associated lock or monitor. Putting code inside a synchronized block makes the compiler append instructions to acquire the lock on the specified object before executing the code, and release it afterwards (either because the code finishes normally or abnormally). Between acquiring the lock and releasing it, a thread is said to "own" the lock. At the point of Thread A wanting to acquire the lock, if Thread B already owns the it, then Thread A must wait for Thread B to release it.

so maybe something like this can work :

synchronized statement in java:

public class Java {
    static private int count = 0;

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

became :

import threading

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

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

and synchronized method in Java:

public class Java {
    static private int count = 0;

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

became:

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

Explicit is better than implicit.

N.B: my knowledge in Java is very limited, and it's my first lecture about this Java feature so maybe i miss something (or maybe i miss all the point here :) ), well hope this answer can help someone.

N.B: the lock that i have created is a class variable so threading synchronization happen in class level, if we want to make the synchronization in instance level (only) which i think that how java do it, the code above must change.

like image 133
mouad Avatar answered Sep 28 '22 12:09

mouad


I sometimes use a decorator like this:

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

This solution has a race condition when calling the decorated method for the first time, though. The simplest way to avoid this problem is to call one synchronized method when no other threads are running first, or to assign the self._lock manually in __init__

like image 26
cube Avatar answered Sep 28 '22 13:09

cube