Welcome, guest | Sign In | My Account | Store | Cart

A lock object that allows many simultaneous "read-locks", but only one "write-lock".

Python, 39 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import threading

class ReadWriteLock:
    """A lock object that allows many simultaneous "read-locks", but
    only one "write-lock"."""
    
    def __init__(self):
        self._read_ready = threading.Condition(threading.Lock())
        self._readers = 0

    def acquire_read(self):
        """Acquire a read-lock. Blocks only if some thread has
        acquired write-lock."""
        self._read_ready.acquire()
        try:
            self._readers += 1
        finally:
            self._read_ready.release()

    def release_read(self):
        """Release a read-lock."""
        self._read_ready.acquire()
        try:
            self._readers -= 1
            if not self._readers:
                self._read_ready.notifyAll()
        finally:
            self._read_ready.release()

    def acquire_write(self):
        """Acquire a write lock. Blocks until there are no
        acquired read- or write-locks."""
        self._read_ready.acquire()
        while self._readers > 0:
            self._read_ready.wait()

    def release_write(self):
        """Release a write-lock."""
        self._read_ready.release()

It is often convenient to allow unlimited read access to a resource when it is not being modified and still keep write access exclusive. While the 'threading' module does not contain a specific class for the job, the idiom is easy to implement using a Condition object.

2 comments

vic_d_v 19 years, 5 months ago  # | flag

How do you prevent from new connections reading the data. From your code it looks like this code allows new connections to read the data and in some cases the code will not ever allow to update the data.

James Reeves 15 years, 11 months ago  # | flag

This is just a threaded lock; it's up to the programmer to make sure that more than unmanaged connections don't try to access the same file. Also, as far as I can see, there's no source of conflict in this code. Certainly it's performed well in my tests, and I've gone through the code fairly thoroughly...