线程-锁
1"""
2Author: wangy325
3Date: 2024-08-07 19:38:19
4Description: 锁
5"""
6from threading import Thread, Lock, current_thread
7
8"""
9python中没有类似Java synchronised同步关键字, 使用锁与条件来实现同步。
10"""
11
12# ############### #
13# 锁 #
14# ############### #
15
16shared_int = 0
17lock = Lock()
18
19
20def incr_n_times(n):
21 """
22 挺离谱的, 明明可以看到线程竞争都乱成一锅粥了
23 最后的结果竟然是正确的 :-)
24 """
25 global shared_int
26 print(f"{current_thread().name}: >>>>{shared_int}")
27 for i in range(n):
28 shared_int += 1
29 print(f"{current_thread().name}: <<<<{shared_int}")
30
31
32def safe_incr_n_times(n):
33 global shared_int
34 lock.acquire()
35 print(f"{current_thread().name}: >>>>{shared_int}")
36 for i in range(n):
37 shared_int += 1
38 print(f"{current_thread().name}: <<<<{shared_int}")
39 lock.release()
40
41
42def incr_with_x_threads(x, func, n):
43 # 列表推导式
44 threads = [Thread(target=func, args=(n,)) for i in range(x)]
45 start = time.time()
46 global shared_int
47 shared_int = 0
48 for t in threads:
49 t.start()
50 for t in threads:
51 t.join()
52 print(f"finished in {time.time() - start}\n"
53 f"shared expected: {n * x}\n"
54 f"shared actual: {shared_int}\n"
55 f"difference: {n * x - shared_int}({100 - shared_int / n / x * 100}%)")
56
57
58# ############################## #
59# 这个栗子更好证明线程对资源的争夺 #
60# ############################## #
61balance = 100
62
63
64def withdraw_unsafe(money):
65 """
66 很明显可以看到2个线程同时进来, 同时获得最大余额
67 :param money:
68 :return:
69 """
70 global balance
71 if balance >= money:
72 time.sleep(1)
73 balance -= money
74 print(f"{current_thread().name}: withdraw {money}")
75 else:
76 print(f"{current_thread().name}: balance ({balance} < {money}) not enough")
77
78
79def withdraw_safe(money):
80 global balance
81 lock.acquire()
82 if balance >= money:
83 balance -= money
84 print(f"{current_thread().name}: withdraw {money}")
85 else:
86 print(f"{current_thread().name}: balance ({balance} < {money}) not enough")
87 lock.release()
88
89
90def withdraw_multi_t(func, m):
91 threads = [Thread(target=func, args=(m,)) for i in range(2)]
92 for t in threads:
93 t.start()
94 for t in threads:
95 t.join()
96 print(f"balance: {balance}")
97
98
99if __name__ == '__main__':
100 # incr_with_x_threads(10, incr_n_times, 1000000)
101 # incr_with_x_threads(10, safe_incr_n_times, 1000000)
102 withdraw_multi_t(withdraw_unsafe, 80)
103 # withdraw_multi_t(withdraw_safe, 80)