一直在想,python和java的synchronized等价的是什么,怎么实现同步呢?
为了测试同步,我们用5个线程同时进行累加,每次加1进行1000000次。
如果同步成功,那么结果是5000000。
我们分别用正确的lock加锁方式,不加锁,错误的加锁方式来进行对比。
正确的加锁方式:target_function1
不加锁:target_function2
错误的加锁方式:target_function3
import time
import threading
count1 = 0 # 正确加锁方式初始值
count2 = 0 # 不加锁
count3 = 0 # 错误的加锁方式初始值
iter_times = 1000000 # 累加次数
# 加锁
def target_function(lock):
global count1, iter_times
lock.acquire()
# do something... 养成好习惯,万一报错了要释放锁!
try:
for i in range(iter_times):
count1 += 1
time.sleep(1)
print(threading.current_thread())
finally:
lock.release()
# 不加锁
def target_function2():
global count2, iter_times
for i in range(iter_times):
count2 += 1
print(threading.current_thread())
# 加了个假锁
def target_function3():
global count3, iter_times
lock = threading.Lock()
lock.acquire()
# do something... 养成好习惯,万一报错了要释放锁!
try:
for i in range(iter_times):
count3 += 1
time.sleep(1)
print(threading.current_thread())
finally:
lock.release()
接下来我们开始运行:
def main():
lock = threading.Lock()
print(threading.current_thread())
name = 't'
for i in range(5):
name_i = name + str(i)
t1 = threading.Thread(target=target_function, name=name_i, args=[lock])
t2 = threading.Thread(target=target_function2, name=name_i)
t3 = threading.Thread(target=target_function3, name=name_i)
t1.start()
t2.start()
t3.start()
time.sleep(10)
print(count1)
print(count2)
print(count3)
if __name__ == '__main__':
main()
输出如下:
5000000
3381388
3675932
可以看到,只有第一种方式加锁是正确的,正确得实现了同步。
第三种方式为什么错?
因为每个线程申请了一把新的锁,没锁住同一个东西。
还有其它方式让累加结果正确吗?
在t2.start()之后加入t2.join(),但是这样就变成了串行。
本文不足之处?
改成线程池,另外python还有多进程。由multiprocessing提供。