python3:多线程锁的好例子,值得好好思考

多线程共享全局变量时,当多个线程同时对同一共享资源(变量)进行操作(计算)时,可能会出现抢夺资源的情况,从而导致计算结果非预期. 
为什么为出现这种情况呢?
如下面这句话:
g_num += 1
看似简单,但是python在执行时,会分成好几步来执行:
step1. 先获取g_num值
step2. 计算g_num = g_num + 1
step3. 赋值给g_num

想想,如果同时有两个或多个线程同时对global变量进行这个操作,当线程1执行到step1后,可能系统资源被线程2抢夺去了,则线程2就会执行step1, 当线程2执行完step3时,g_num已改变,这时系统资源又被线程1给抢走了,而开始计算线程1的step2,则会导致线程1的计算有误,当计算量越大时,其结果就错的越离谱. 

所以
线程锁就是为了解决这一问题,锁可以锁定资源,当被锁的资源被操作完成后,再释放资源,这样就保证了资源操作的准确性. 
下面三个实例。
1. 多线程同时操作全局变量时计算结果错误。

import threading
from time import sleep

g_num = 0
mutex = threading.Lock()

def addnum1(num):
    global g_num
    for i in range(1, num):
        g_num += 1
    print(f'addnum1()::g_num:{g_num}')


def addnum2(num):
    global g_num
    for i in range(1, num):
        g_num += 1
    print(f'addnum2()::g_num:{g_num}')


def main():
    t1 = threading.Thread(target=addnum1, args=(100001,))
    t2 = threading.Thread(target=addnum2, args=(100001,))
    t1.start()
    t2.start()

    sleep(1)
    print(f'\n-----------{g_num}-----------')


if __name__ == "__main__":
    main()


2. 多线程同时操作全局变量时加锁加在'g_num += 1'前后时,addnum1/addnum2函数总有一个结果不合预期. 

import threading
from time import sleep

g_num = 0
mutex = threading.Lock()

def addnum1(num):
    global g_num
    for i in range(1, num):
        mutex.acquire()
        g_num += 1
        mutex.release()
    print(f'addnum1()::g_num:{g_num}')


def addnum2(num):
    global g_num
    for i in range(1, num):
        mutex.acquire()
        g_num += 1
        mutex.release()
    print(f'addnum2()::g_num:{g_num}')


def main():
    t1 = threading.Thread(target=addnum1, args=(100001,))
    t2 = threading.Thread(target=addnum2, args=(100001,))
    t1.start()
    t2.start()

    sleep(1)
    print(f'\n-----------{g_num}-----------')


if __name__ == "__main__":
    main()


3. 多线程同时操作全局变量时加锁加在'for'前后时,addnum1/addnum2函数结果完全符合预期.

import threading
from time import sleep

g_num = 0
mutex = threading.Lock()

def addnum1(num):
    global g_num
    mutex.acquire()
    for i in range(1, num):
        g_num += 1
    mutex.release()
    print(f'addnum1()::g_num:{g_num}')


def addnum2(num):
    global g_num
    mutex.acquire()
    for i in range(1, num):
        g_num += 1
    mutex.release()
    print(f'addnum2()::g_num:{g_num}')


def main():
    t1 = threading.Thread(target=addnum1, args=(100001,))
    t2 = threading.Thread(target=addnum2, args=(100001,))
    t1.start()
    t2.start()

    sleep(1)
    print(f'\n-----------{g_num}-----------')


if __name__ == "__main__":
    main()

1、2、3值得好好思考,是个好例子. 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值