Day05 Python中的线程、互斥锁等

一、多任务

1、多任务的定义

多种任务同时进行

2、多任务的执行方式

1.并发:多个任务在同一时间段内串行交替执行。

2.并行:多个任务在同一时刻内相互独立且同时执行。
在这里插入图片描述

二、多线程

Pass:说道线程,必须要首先介绍一下进程是什么?

进程:

  • 运行的程序或软件,它是操作系统进行资源分配的基本单位;比如我们运行的.py文件就是一个进程;
  • 一个进程默认有一个线程,进程里可以创建多个线程,线程是依附在进程里的,没有进程就没有线程。

1、线程的定义

是进程中执行代码的一个分支,每个执行分支要想工作执行代码,需要cpu进行调度,也就是说线程是cpu调度的基本单位。

用下面的图帮助我们去了解进程与线程之间的关系:

在这里插入图片描述

2、创建单线程

例1

import time
def question():
    print('夏天到了')
    time.sleep(1)
    print('大家都开空调了吗?')
def answer():
    print('哈哈')
    time.sleep(2)
    print('那是当然的了!')
if __name__ =='__main__': # python模拟的程序入口,表示直接运行时,执行里面的代码
    question()
    answer()


 **结果**:
夏天到了
(中间停留1s)
大家都开空调了吗?
哈哈
(中间停留2s)
那是当然的了!

例2

import time
def dance(name):
    print(f'{name}在跳See ya')
    time.sleep(4)
if __name__=='__main__':
    for i in range(2):
        dance('任嘉伦')#调用dance函数,并且name=任嘉伦


**结果**:
任嘉伦在跳See ya
(中间停留4s)
任嘉伦在跳See ya

3、创建多线程

1.步骤:

  • 1.导入模块 threading
  • 2.创建子线程 Thread类
  • 3.可设置守护线程 setDaemon() 主线程执行完了,子线程也会跟着结束
  • 4.启动子线程 start()
  • 5.可设置阻塞主线程 join() 阻塞主线程,等待子线程执行完

例1:多进程

import threading#导入进程方式1
import time
def dance(name):
    print(f'{name}在跳See ya')
    time.sleep(1)
if __name__ == '__main__':
    for i in range(2):
        # 创建线程
        t = threading.Thread(target=dance,args=('任嘉伦',))
        #启动线程
        t.start()


结果:
任嘉伦在跳See ya
(中间间隔非常短)
任嘉伦在跳See ya

例2:多线程进阶,添加守护线程

import time
from threading import Thread#导入线程方式2
def f1():
    print('任嘉伦')
    time.sleep(1)
    print('任嘉伦是我的偶像')
def f2():
    print('好好学习')
    time.sleep(1)
    print('你就能见他了!')
if __name__=='__main__':
    # 创建线程
    f1 = Thread(target=f1)
    f2 = Thread(target=f2)
    # 设置守护线程
    f1.setDaemon(True)
    f2.setDaemon(True)
    # 启动线程
    f1.start()
    f2.start()
    print('哈哈!')

结果:
任嘉伦  
(f1中的“任嘉伦是我的偶像”还没执行,主线程就先执行完了)
好好学习 
(f2中的“你就能见他了!”还没有执行,主线程就先执行完了)
哈哈!

例3:多线程进阶,添加阻塞主线程,不添加守护线程

import time
from threading import Thread
def f1():
    print('任嘉伦')
    time.sleep(0.1)
    print('任嘉伦是我的偶像')
def f2():
    print('好好学习')
    time.sleep(2)
    print('你就能见他了!')
if __name__ == '__main__':
    # 创建线程
    f1 = Thread(target=f1)
    f2 = Thread(target=f2)
    # 启动线程
    f1.start()
    f2.start()
    # 阻塞主线程----"我(主线程)等你(子线程)"
    f1.join()
    f2.join()
    print('哈哈!')

# 结果:
# 任嘉伦
# 好好学习
# 任嘉伦是我的偶像
# 你就能见他了!
# 哈哈!

例4:多线程进阶,添加阻塞主线程,添加守护线程

import time
from threading import Thread
def f1():
    print('任嘉伦')
    time.sleep(0.1)
    print('任嘉伦是我的偶像')
def f2():
    print('好好学习')
    time.sleep(2)
    print('你就能见他了!')
if __name__ == '__main__':
    # 创建线程
    f1 = Thread(target=f1)
    f2 = Thread(target=f2)
    # 设置守护线程
    f1.setDaemon(True)
    f2.setDaemon(True)
    # 启动线程
    f1.start()
    f2.start()
    # 阻塞主线程----"我(主线程)等你(子线程)"
    f1.join()
    f2.join()
    print('哈哈!')

# 结果:
# 任嘉伦
# 好好学习
# 任嘉伦是我的偶像
# 你就能见他了!
# 哈哈!

例5:多线程进阶,修改名字和获取名字

import time
from threading import Thread
def f1():
    print('任嘉伦')
    time.sleep(1)
    print('任嘉伦是我的偶像')
def f2():
    print('好好学习')
    time.sleep(2)
    print('你就能见他了!')

if __name__ == '__main__':
    # 创建线程
    f1 = Thread(target=f1)
    f2 = Thread(target=f2)
    # 启动线程
    f1.start()
    f2.start()
    # 阻塞主线程----"我(主线程)等你(子线程)"
    f1.join()
    f2.join()
    # 修改名字
    f1.setName('Allen')
    f2.setName('任国超')
    # 获取名字
    print(f1.getName())
    print(f2.getName())
    print('哈哈!')


#结果:
# 任嘉伦
# 好好学习
# 任嘉伦是我的偶像
# 你就能见他了!
# Allen
# 任国超
# 哈哈!

2.线程执行代码的封装

from threading import Thread
import time
class Ourthread(Thread):
    # 重写run方法
    def run(self):
        print('任嘉伦')
        time.sleep(7)
        print('你们认识吗?')
if __name__ == '__main__':
    t1 = Ourthread()
    t1.start()

结果:
任嘉伦
你们认识吗?

3.结论

结论1:线程之间执行是无序的"

import threading    # 导入线程模块
import time
def task():
    time.sleep(2)
    print(f'当前线程名为:{threading.current_thread().name}\n', end='')
    # print(f'当前线程名为:{threading.current_thread().name}\n',end='')

if __name__ == '__main__':
    for i in range(3):
        # 创建线程
        t = threading.Thread(target=task)
        # 启动线程
        t.start()



# 结果:执行第1次
# 当前线程名为:Thread-1
# 当前线程名为:Thread-3
# 当前线程名为:Thread-2

# 执行第2次:
# 当前线程名为:Thread-1
# 当前线程名为:Thread-2
# 当前线程名为:Thread-3

结论2:多线程资源共享

from threading import Thread   # 导入线程模块的另一种方式
import time
list = []   # 全局变量,空列表
# 写数据
def writedata():
    for i in range(5):
        list.append(i)   # 添加i到lst列表
        time.sleep(0.2) # 睡眠0.2s
    print('写入数据:',list)

# 读数据
def readdata():
    print('读取的数据:',list)

if __name__ == '__main__':
    # 创建线程
    wd = Thread(target=writedata)
    rd = Thread(target=readdata)
    # 启动线程
    wd.start()
    rd.start()
# 结果:
# 读取的数据: [0](写数据还没写完,就读取了)
# 写入数据: [0, 1, 2, 3, 4]

结论3:线程之间存在资源竞争

from threading import Thread
a = 0
b = 1000000
def sum1():
    for i in range(b):
        global a
        a += 1
    print(f'第一次:{a}\n',end='')

def sum2():
    for i in range(b):
        global a
        a += 1
    print(f'第二次:{a}\n',end='')
# sum2()
if __name__ == "__main__":
    # 创建线程
    t1 = Thread(target=sum1)
    t2 = Thread(target=sum2)
    # 启动线程
    t1.start()
    t2.start()

# 结果:
# 第二次:1549492
# 第一次:1680705

Pass:资源竞争有什么解决的办法呢?

三、 互斥锁

资源竞争解决的办法 :互斥锁
1、定义:
在这里插入图片描述
普通的,不使用线程:

a = 0
b = 1000000

def sum1():
    for i in range(b):
        global a
        a += 1
    print(f'第一次:{a}\n',end='')
sum1()#

def sum2():

    for i in range(b):
        global a
        a += 1
    print(f'第二次:{a}\n',end='')
sum2()

结果:
第一次:1000000
第二次:2000000

使用进程,互斥锁解决:

from threading import Thread,Lock
a = 0
b = 1000000
# 创建全局互斥锁
lock = Lock()
def sum1():
    lock.acquire()    # 加锁   
    for i in range(b):
        global a
        a += 1
    print(f'第一次:{a}\n',end='')
    lock.release()   # 解锁
# sum1()
def sum2():
    lock.acquire()
    for i in range(b):
        global a
        a += 1
    print(f'第二次:{a}\n',end='')
    lock.release()
    
if __name__ == "__main__":
    # 创建线程
    t1 = Thread(target=sum1)
    t2 = Thread(target=sum2)
    # 启动线程
    t1.start()
    t2.start()

结果:
第一次:1000000
第二次:2000000

四、同步

1、定义:
在这里插入图片描述
使用join()解决:

from threading import Thread
a = 0
b = 1000000

def sum1():
    for i in range(b):
        global a
        a += 1
    print(f'第一次:{a}\n',end='')

def sum2():

    for i in range(b):
        global a
        a += 1
    print(f'第二次:{a}\n',end='')

if __name__ == "__main__":
    # 创建线程
    t1 = Thread(target=sum1)
    t2 = Thread(target=sum2)
    # 启动线程
    t1.start()
    t1.join()   # 解决资源竞争join()方式
    t2.start()
    t2.join()

结果:
第一次:1000000
第二次:2000000
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值