Synchronization mixin in Python anyone?

Chris Liechti cliechti at gmx.net
Fri May 3 22:28:15 EDT 2002


sorry if this msg show up multiple times - i had troubles posting...

Sean McGrath <sean.mcgrath at propylon.com> wrote in 
news:mailman.1020454627.587.python-list at python.org:
> The Zope system contains a Synchronization mixin class
> for thread synchronization written in C. Derive a class from Synchronized
> and any mythod calls on an instance of the class are
> thread safe.
> 
> Does anybody know of any Python implementation? The C version
> exhibits "interesting" refcounting behavior I need to work around.

not exactly what you asked for but solving exactly that problem...

i attched my attempt to make a method "synchronized" (like known from 
Java). as you will see in the source comment, there is a small problem on 
the first use of a sync'd method.
someone on the group with a solution appart from derriving from a special 
base class "Synchronized" which does allocate the condition object? (yes 
that works but it's a lot more typing and the user has the "chance" to 
forget the __init__ of it etc. )-:

chris

---------------synchronized.py
#! /usr/bin/env python
#
# emulate Java's synchronized methods through a threading.Condition object
# python 2.1+ required
# cliechti at gmx.net

from __future__ import nested_scopes    #for those who still use 2.1 ;-)
import threading

def synchronized(f):
    """use this method like "staticmethod" to wrap methods in a class."""
    def syncwrap(self, *args,**kwargs):
        #first of all there is no lock, the moment where one is created
        #is critical - if two or more threads enter a sync'd method on a
        #"fresh" instance both might create a __lock but the first one
        #looses his Condition object which was overwriten by the second
        #thread. one solution could be to implement the wrap function in
        #c and enable threading right before the wrapped method is called.
        try:
            self.__lock.acquire()
        except AttributeError:  #lock does not yet exist (first time use)
            self.__lock = threading.Condition()
            self.__lock.acquire()
            #mirror those practical methods on the instance itself
            self.wait = self.__lock.wait
            self.notifyAll = self.__lock.notifyAll
            self.notify = self.__lock.notify
        try:
            return f(self, *args,**kwargs)
        finally:
            self.__lock.release()
    return syncwrap

if __name__ == '__main__':
    #testing...
    class B:
        def f(self):
            import time
            print "waiting for 3 seconds...",
            time.sleep(3)
            print "ok"
        f = synchronized(f)

        def g(self):
            print "just g()"
        g = synchronized(g)


        def cons(self):
            print "cons() waiting..."
            self.wait()
            print "cons() ok"
        cons = synchronized(cons)

        def prod(self):
            print "prod() notify"
            self.notifyAll()
        prod = synchronized(prod)

    b=B()
    #simple locking test
    threading.Timer(1, b.g).start()     #call g while still in f
    b.f()                               #f will take 3 seconds
    #consumer-producer problem test
    threading.Timer(2, b.prod).start()  #call prod after a short delay
    b.cons()                            #wait until prod notifies
    

-- 
Chris <cliechti at gmx.net>




More information about the Python-list mailing list