1

Is there any way to use monitor thread synchronization like java methods synchronization,in python class to ensure thread safety and avoid race condition?

I want a monitor like synchronization mechanism that allows only one method call in my class or object

Pooya
  • 4,385
  • 6
  • 45
  • 73

2 Answers2

6

You might want to have a look at python threading interface. For simple mutual exclusion functionality you might use a Lock object. You can easily do this using the with statement like:

...
lock = Lock()
...
with (lock):
  # This code will only be executed by one single thread at a time
  # the lock is released when the thread exits the 'with' block
  ...

See also here for an overview of different thread synchronization mechanisms in python.

There is no python language construct for Java's synchronized (but I guess it could be built using decorators)

MartinStettner
  • 28,719
  • 15
  • 79
  • 106
2

I built a simple prototype for it, here's a link to the GitHub repository for all the details : https://github.com/m-a-rahal/monitor-sync-python

I used inheritance instead of decorators, but maybe I'll include that option later
Here's what the 'Monitor' super class looks like:

import threading

class Monitor(object):
   def __init__(self, lock = threading.Lock()):
       ''' initializes the _lock, threading.Lock() is used by default '''
       self._lock = lock


   def Condition(self):
       ''' returns a condition bound to this monitor's lock'''
       return threading.Condition(self._lock)

   init_lock = __init__

Now all you need to do to define your own monitor is to inherit from this class:

class My_Monitor_Class(Monitor):
    def __init__(self):
        self.init_lock() # just don't forget this line, creates the monitor's _lock
        cond1 = self.Condition()
        cond2 = self.Condition()
        # you can see i defined some 'Condition' objects as well, very simple syntax
        # these conditions are bound to the lock of the monitor

you can also pass your own lock instead

class My_Monitor_Class(Monitor):
    def __init__(self, lock):
        self.init_lock(lock)

check out threading.Condition() documentation

Also you need to protect all the 'public' methods with the monitor's lock, like this:

class My_Monitor_Class(Monitor):
    def method(self):
        with self._lock:
            # your code here

if you want to use 'private' methods (called inside the monitor), you can either NOT protect them with the _lock (or else the threads will get stuck), or use RLock instead for the monitor

EXTRA TIP

sometimes a monitor consists of 'entrance' and 'exit' protocols

monitor.enter_protocol()
<critical section>
monitor.exit_protocol()

in this case, you can exploit python's cool with statement :3
just define the __enter__ and __exit__ methods like this:

class monitor(Monitor):
    def __enter__(self):
        with self._lock:
            # enter_protocol code here
    
    def __exit__(self, type, value, traceback):
        with self._lock:
            # exit_protocol code here

now all you need to do is call the monitor using with statement:

with monitor: 
    <critical section>
M.A. Rahal
  • 21
  • 3