/
6_read_write_lock.py
121 lines (92 loc) · 2.87 KB
/
6_read_write_lock.py
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import random
import threading
from time import sleep
class ReadWriteLock:
def __init__(self):
self.reading_readers = 0
self.waiting_writers = 0
self.writing_writers = 0
self.prefer_writer = True
self.cv = threading.Condition()
def read_lock(self):
with self.cv:
while self.writing_writers > 0 or (self.prefer_writer and self.waiting_writers > 0):
self.cv.wait()
self.reading_readers += 1
def read_unlock(self):
with self.cv:
self.reading_readers -= 1
self.prefer_writer = True
self.cv.notify_all()
def write_lock(self):
with self.cv:
self.waiting_writers += 1
while self.reading_readers > 0 or self.writing_writers > 0:
self.cv.wait()
self.waiting_writers -= 1
self.writing_writers += 1
def write_unlock(self):
with self.cv:
self.writing_writers -= 1
self.prefer_writer = False
self.cv.notify_all()
class Data:
def __init__(self, size):
self.buffer = ["*"] * size
self.lock = ReadWriteLock()
def read(self):
self.lock.read_lock()
c = self.do_read()
self.lock.read_unlock()
return c
def write(self, c):
self.lock.write_lock()
self.do_write(c)
self.lock.write_unlock()
def do_read(self):
self.slowly()
return self.buffer[:]
def do_write(self, c):
for i in range(len(self.buffer)):
self.buffer[i] = c
self.slowly()
@staticmethod
def slowly():
sleep(0.1)
class ReaderThread(threading.Thread):
def __init__(self, data):
super(ReaderThread, self).__init__()
self.data = data
def run(self):
print(" Reader thread start", self.name)
for i in range(10000):
read_buf = self.data.read()
print(threading.current_thread().name + " reads " + "".join(read_buf))
class WriterThread(threading.Thread):
def __init__(self, data, filler):
super(WriterThread, self).__init__()
self.data = data
self.filler = filler
self.index = 0
def run(self):
print(" Writer thread start", self.name)
for i in range(10000):
c = self.next_char()
self.data.write(c)
sleep(random.uniform(0, 0.1))
def next_char(self):
c = self.filler[self.index]
self.index += 1
if self.index >= len(self.filler):
self.index = 0
return c
def main():
data = Data(19)
WriterThread(data, "ABCDEFGHIJKLMNOP").start()
WriterThread(data, "abcdefghijklmnop").start()
ReaderThread(data).start()
ReaderThread(data).start()
ReaderThread(data).start()
ReaderThread(data).start()
ReaderThread(data).start()
main()