python多线程使用lock实现同步

一直在想,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提供。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值