Skip to content

Commit 8d8c2eb

Browse files
committed
finish ch2.7
1 parent e1e514f commit 8d8c2eb

3 files changed

+82
-4
lines changed

chapter2/06_Thread_synchronization_with_Lock_and_Rlock.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
使用Lock和RLock进行线程同步
1+
使用Lock进行线程同步
22
===========================
33

44
当两个或以上对共享内存的操作发生在并发线程中,并且至少有一个可以改变数据,又没有同步机制的条件下,就会产生竞争条件,可能会导致执行无效代码、bug、或异常行为。
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,83 @@
11
使用RLock进行线程同步
22
=====================
33

4+
如果你想让只有拿到锁的线程才能释放该锁,那么应该使用 ``RLock()`` 对象。和 ``Lock()`` 对象一样, ``RLock()`` 对象有两个方法: ``acquire()`` 和 ``release()`` 。当你需要在类外面保证线程安全,又要在类内使用同样方法的时候 ``RLock()`` 就很实用了。
45

6+
(译者注:RLock原作解释的太模糊了,译者在此擅自添加一段。RLock其实叫做“Renntrant Lock”,就是可以重复进入的锁,也叫做“递归锁”。这种锁对比Lock有是三个特点:1. 谁拿到谁释放。如果线程A拿到锁,线程B无法释放这个锁,只有A可以释放;2. 同一线程可以多次拿到该锁,即可以acquire多次;3. acquire多少次就必须release多少次,只有最后一次release才能改变RLock的状态为unlocked)
7+
8+
|how|
9+
-----
10+
11+
在示例代码中,我们引入了 ``Box`` 类,有 ``add()`` 方法和 ``remove()`` 方法,提供了进入 ``execute()`` 方法的入口。 ``execute()`` 的执行由 ``Rlock()`` 控制: ::
12+
13+
import threading
14+
import time
15+
16+
class Box(object):
17+
lock = threading.RLock()
18+
19+
def __init__(self):
20+
self.total_items = 0
21+
22+
def execute(self, n):
23+
Box.lock.acquire()
24+
self.total_items += n
25+
Box.lock.release()
26+
27+
def add(self):
28+
Box.lock.acquire()
29+
self.execute(1)
30+
31+
def remove(self):
32+
Box.lock.acquire()
33+
self.execute(-1)
34+
Box.lock.release()
35+
36+
## These two functions run n in separate
37+
## threads and call the Box's methods
38+
def adder(box, items):
39+
while items > 0:
40+
print("adding 1 item in the box")
41+
box.add()
42+
time.sleep(1)
43+
items -= 1
44+
45+
def remover(box, items):
46+
while items > 0:
47+
print("removing 1 item in the box")
48+
box.remove()
49+
time.sleep(1)
50+
items -= 1
51+
52+
## the main program build some
53+
## threads and make sure it works
54+
if __name__ == "__main__":
55+
items = 5
56+
print("putting %s items in the box " % items)
57+
box = Box()
58+
t1 = threading.Thread(target=adder, args=(box, items))
59+
t2 = threading.Thread(target=remover, args=(box, items))
60+
t1.start()
61+
t2.start()
62+
63+
t1.join()
64+
t2.join()
65+
print("%s items still remain in the box " % box.total_items)
66+
67+
运行结果如下:
68+
69+
.. image:: ../images/Page-68-Image-10.png
70+
71+
|work|
72+
------
73+
74+
主程序的代码几乎和之前的例子一样。两个线程 ``t1`` 和 ``t2`` 分别分配了 ``adder()`` 函数和 ``remover()`` 函数。当item的数量大于0的时候,函数工作。调用 ``RLock()`` 的位置是在 ``Box`` 类内: ::
75+
76+
class Box(object):
77+
lock = threading.RLock()
78+
79+
``adder()`` 和 ``remover()`` 两个函数在 ``Box`` 类内操作items,即调用 ``Box`` 类的方法: ``add()`` 和 ``remove()`` 。每一次方法调用,都会有一次拿到资源然后释放资源的过程。至于 ``lock()`` 对象, ``RLock()`` 对象有 ``acquire()`` 和 ``release()`` 方法可以拿到或释放资源;然后每一次方法调用中,我们都有以下操作: ::
80+
81+
Box.lock.acquire()
82+
# ...do something
83+
Box.lock.release()

chapter2/box.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ def execute(self, n):
1515
def add(self):
1616
Box.lock.acquire()
1717
self.execute(1)
18-
Box.lock.release()
1918

2019
def remove(self):
2120
Box.lock.acquire()
@@ -28,14 +27,14 @@ def adder(box, items):
2827
while items > 0:
2928
print("adding 1 item in the box")
3029
box.add()
31-
time.sleep(5)
30+
time.sleep(1)
3231
items -= 1
3332

3433
def remover(box, items):
3534
while items > 0:
3635
print("removing 1 item in the box")
3736
box.remove()
38-
time.sleep(5)
37+
time.sleep(1)
3938
items -= 1
4039

4140
## the main program build some

0 commit comments

Comments
 (0)