线程共享全局变量出错

解决办法

多任务编程
线程同步: 保证同一时刻只能有一个线程去操作全局变量 。
同步: 就是协同步调,按预定的先后次序进行运行。
线程同步的两种方式:
1、线程等待(join)
2、互斥锁

线程共享全局变量出错的两种解决办法:

方法一:线程等待(join)

利用线程等待,即子线程.join()的方法让当前线程(主线程)等待添加数据的线程执行完成后代码在继续执行

import threading

# 定义一个全局变量
g_num = 0

def first_data():
    for i in range(1000000):
        # 声明全局变量
        global g_num
        g_num += 1

    print('第一个:', g_num)

def second_data():
    for i in range(1000000):
        # 声明全局变量
        global g_num
        g_num += 1

    print('第二个:', g_num)

if __name__ == '__main__':
    # 创建第一个子线程
    first_thread = threading.Thread(target=first_data)

    # 创建第二个子线程
    second_thread = threading.Thread(target=second_data)

    first_thread.start()

    # 让当前线程(主线程)等待添加数据的线程执行完成后代码再继续执行
    first_thread.join()  
    second_thread.start()

第一个: 1000000
第二个: 2000000

方法二:互斥锁

import threading

# 创建锁, Lock 本质上是一个函数,通过调用这个函数可以获取一把互斥锁
lock = threading.Lock()
# 定义一个全局变量
g_num = 0

def first_data():
    # 上锁
    lock.acquire()
    for i in range(1000000):
        # 声明全局变量
        global g_num
        g_num += 1

    print('第一个:', g_num)
    # 释放锁
    lock.release()

def second_data():
    # 上锁
    lock.acquire()
    for i in range(1000000):
        # 声明全局变量
        global g_num
        g_num += 1

    print('第二个:', g_num)
    # 释放锁
    lock.release()

if __name__ == '__main__':
    # 创建第一个子线程
    first_thread = threading.Thread(target=first_data)
    # 创建第二个子线程
    second_thread = threading.Thread(target=second_data)

    first_thread.start()
    second_thread.start()

# 线程等待和互斥锁都是把多任务改成单任务去执行,保证了数据的准确性,但是执行性能会下降.

拓展:使用互斥锁的时候要注意死锁问题。
死锁:等待对方释放锁的状态称为死锁。后面的代码无法正常执行。
下面举个例子:

# 目的: 根据下标在列表中取值, 保证同一时刻只能有一个线程去取值
import threading

# 创建锁
lock = threading.Lock()

def get_value(index):
    # 上锁
    lock.acquire()
    list1 = [1, 3, 5]
    # 判断下标是否越界
    if index >= len(list1):
        print('下标越界', index)
        # return 会退出当前函数, 退出前需要释放锁
        # lock.release()   # 注意要释放锁
        return
    value = list1[index]
    print(value)
    # 释放锁
    lock.release()

if __name__ == '__main__':
    # 循环创建多个子线程
    for i in range(10):
        sub_thread = threading.Thread(target=get_value, args=(i,))
        sub_thread.start()

return前未释放锁:
1
3
5
下标越界 3
return前释放锁:
1
3
5
下标越界 3
下标越界 4
下标越界 5
下标越界 6
下标越界 7
下标越界 8
下标越界 9

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值