Python菜鸟编程第十七课之多线程变量共享

Python菜鸟编程第十七课之多线程变量共享

1.多线程—共享全局变量问题

1.1

假设有两个线程t1和t2,都要对一个变量g_num进行运算(+1),两个线程t1和t2分别对g_num+1

demo:

import threading
import time

g_num = 0


def work1(num):
    global g_num
    for i in range(num):
        g_num += 1
    print('---in work1,g_num is %d----' % g_num)


def work2(num):
    global g_num
    # t_start=time.time()
    for i in range(num):
        g_num += 1
    print('---in work2,g_num is %d----' % g_num)
    # t_end = time.time()
    # print('work2 运行时间:',t_end-t_start)

def main():
    print('线程创建之前g_num 的值为:%d' % g_num)
    t1 = threading.Thread(target=work1, args=(10,))
    t2 = threading.Thread(target=work2, args=(10,))

    # t1 = threading.Thread(target=work1)
    # t2 = threading.Thread(target=work2)

    t1.start()
    t2.start()

    while len(threading.enumerate())!=1:
        time.sleep(1)
    # time.sleep(5)
    print('线程创建之后g_num 的值为:%d' % g_num)


if __name__ == '__main__':
    main()
运行结果:
线程创建之前g_num 的值为:0
---in work1,g_num is 10----
---in work2,g_num is 20----
线程创建之后g_num 的值为:20

一种可能的情况:

在num=0时,t1取得num=0,此时系统把t1调度为“sleeping"的状态,t2转换为”runing"的状态,t2也获得num=0。然后t2对得到的值+1,并赋值给num,num=1。然后系统又将t2调度为“sleeping"的状态,把t1转换为"running",线程t1又把他之前得到的0加1后赋值给num。这种情况,明明两个线程都完成一次+1工作,但结果还是num=1。

当我们将两个进程的参数调整为1000000时,每次运行的结果都不相同。说明多个线程同时对一个全局变量进行操作,会出现资源竞争问题,从而数据结果会不正确。导致线程安全问题。

2.同步

同步就是协同步调。按照预定的先后次序进行运行。

进程和线程同步,可以理解为进程或者线程A和B一块配合,A执行到一定程度时需要依赖B的某个结果让自己暂时停止运行让B运行,B运行后,再将结果给A,A再继续操作。如此往复,直到程序结束。

2.1计算错误的解决

思路:

  • 系统调度t1,获取num=0,此时上一把锁,即不予许其他线程操作num
  • num+1
  • 解锁,此时num=1,其他线程就可以使用num了,此时num=1
  • 同理其他线程在对num修改时,也要先上锁,处理完后再解锁。在上锁的过程中,不允许其他线程访问。这就确保了数据的准确性。

2.2互斥锁

当多个线程几乎同时修改某个共享数据时,需要同步控制。

线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制就是引入同步锁。

2.3死锁

在线程间共享多个资源时,如果两个线程分别占用一部分资源,并且同时等待对方的资源,就会造成死锁。

死锁一般很少发生,但一旦发生就会造成应用停止响应。

demo:

import threading
import time

printer_mutex = threading.Lock() # 打印机锁

paper_mutext = threading.Lock() # 纸张锁


class ResumeThread(threading.Thread):
    """编写个人简历任务的线程"""

    def run(self):
        print("ResumeThread:编写个人简历任务")
        # 使用打印机资源,先对打印机加锁
        printer_mutex.acquire()
        print("--ResumeThread:正在使用打印机资源--")
        time.sleep(1)  # 休眠1秒

        # 使用纸张耗材,先对纸张耗材加锁
        paper_mutext.acquire()
        print("--正在使用纸张资源--")
        time.sleep(1)
        paper_mutext.release()  # 释放纸张锁

        # 释放打印机锁
        printer_mutex.release()


class PaperListThread(threading.Thread):
    """盘点纸张耗材任务的线程"""

    def run(self):
        print("PaperListThread:盘点纸张耗材任务")
        # 使用纸张耗材,先对纸张耗材加锁
        paper_mutext.acquire()
        print("--PaperListThread:正在盘点纸张耗材--")
        time.sleep(1)  # 休眠1秒

        # 使用打印机资源,打印清单
        printer_mutex.acquire()
        print("--正在使用打印机资源--")
        time.sleep(1)
        printer_mutex.release()  # 释放打印机锁

        # 释放纸张耗材锁
        paper_mutext.release()


if __name__ == '__main__':
    t1 = ResumeThread()
    t2 = PaperListThread()

    t1.start()
    t2.start()

博主QQ:1031748759欢迎批评指正!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值