Python8:线程和进程

1.并发和并行

并发:在逻辑上具备同时处理多个任务的能力(其实每时刻只有一个任务)
并行:物理上在同一时刻执行多个并发任务
在这里插入图片描述

2.线程与进程

一个进程管多个线程,一个进程至少有一个线程
在这里插入图片描述
python多线程是假的,因为python解释器内置同一时间CPU只运行一个线程

import threading
import time
def foo(something):
    for i in range(10):
        print(something)
        time.sleep(1)
#创建线程
t1=threading.Thread(target=foo,args=("看电影",))
t2=threading.Thread(target=foo,args=("听音乐",))
#启动线程
t1.start()
t2.start()

在这里插入图片描述

3.join函数-阻塞主线程

一个主线程,2个子线程t1和t2
需要t1和t2运行结束之前,数据检查不会运行,也就是把主线程阻塞

import threading
import time
def foo(something):
    for i in range(10):
        print(something)
        time.sleep(1)
#创建线程
t1=threading.Thread(target=foo,args=("数据逻辑1",))
t2=threading.Thread(target=foo,args=("数据逻辑2",))
#启动线程
t1.start()
t2.start()
#join在子线程完成运行之前,这个子线程的父线程将一直被阻塞
t1.join()
t2.join()
print("启动数据检查....")

在这里插入图片描述

4.守护线程

消费需求满足后,数据逻辑1和2不需要再运行了,直接退出主线程
如果没有声明守护线程,主线程就要等子线程全部执行完才退出

import threading
import time
def foo(something):
    for i in range(10):
        print(something)
        time.sleep(1)
#创建线程
t1=threading.Thread(target=foo,args=("数据逻辑1",))
t2=threading.Thread(target=foo,args=("数据逻辑2",))
#声明守护线程,必须再start方法之前,声明守护线程
t1.setDaemon(True)
t2.setDaemon(True)
#启动线程
t1.start()
t2.start()
for i in range(10):
    print("消费数据....")
    time.sleep(1)
print("消费需求已经满足了")

4.不安全的并发

场景:
银行卡余额:500元
发工资1000元,买衣服花费200元,二者同时进行
不安全的情况:
(1)发工资的线程拿到了500,加上1000,实际余额为1500元,存入余额
(2)买衣服的线程拿到了500,花费200,实际余额为300元,存入余额
结果:300覆盖了1500,造成损失
解决:加锁–同步锁

import threading,time
account_balance=500
#创建锁--同步锁
lock1=threading.Lock()
#操作账户余额
def foo(num):
    #上锁
    lock1.acquire()
    #局部可以直接使用全局变量,但修改全局变量需要声明对全局变量的引用
    global account_balance
    banlance=account_balance#通过接口调用取到账户余额
    time.sleep(1)
    banlance=banlance+num
    #计算结束,将结果存辉数据库或通过接口返回新的余额
    account_balance=banlance
    #操作数据结束后,解锁
    lock1.release()
t1=threading.Thread(target=foo,args=(1000,))#银行发工资
t2=threading.Thread(target=foo,args=(-200,))#花钱
#启动线程
t1.start()
t2.start()
t1.join()
t2.join()
print("最终余额",account_balance)

在这里插入图片描述

5.死锁

两个线程都各自占一部分资源,又同时去等待对方的资源,陷入一种僵局

import threading,time
lockA=threading.Lock()#面试官持有的锁
lockB=threading.Lock()#小明的锁
#面试官
def foo1():
    lockA.acquire()#上锁
    print("请解释什么是死锁")
    time.sleep(1)
    lockB.acquire()#小明上锁
    print("解释完发offer")
    time.sleep(1)
    #解锁
    lockA.release()
    lockB.release()
#小明
def foo2():
    lockB.acquire()#上锁
    print("请给我offer")
    time.sleep(1)

    lockA.acquire()#上锁
    print("发offer再解锁什么是死锁")
    time.sleep(1)
    lockA.release()
    lockB.release()
t1=threading.Thread(target=foo1)
t2=threading.Thread(target=foo2)
t1.start()
t2.start()

在这里插入图片描述

6.解决和预防死锁

递归锁(可重入锁),内部有计数器
用了递归锁:可以多次访问同一个资源

import threading,time
rLock=threading.RLock()#递归锁,也叫可重入锁
#面试官
def foo1():
    rLock.acquire()#上锁
    print("你给我蛋糕")
    time.sleep(1)
    rLock.acquire()#小明上锁
    print("我给你草莓")
    time.sleep(1)
    #解锁
    rLock.release()
    rLock.release()
#小明
def foo2():
    rLock.acquire()#上锁
    print("你给我草莓")
    time.sleep(1)

    rLock.acquire()#上锁
    print("我给你蛋糕")
    time.sleep(1)
    rLock.release()
    rLock.release()
t1=threading.Thread(target=foo1)
t2=threading.Thread(target=foo2)
t1.start()
t2.start()

在这里插入图片描述
读的时候用递归锁,写的时候用同步锁

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值