#多线程
# –多任务:在同一时间内执行多个任务,操作系统可以同时运行多个软件
#多任务的执行方式 :并发 ,并行
# 多线程、多进程执行多任务
#进程和线程
# 进程:运行的程序至少会有一个进程,是操作系统进行资源分配的基本单位
#进程是资源分配的最小单位,他是操作系统进行资源分配和调度运行的基本单位,例如:正在运行的QQ 微信等都是进程
# 一个进程默认有一个线程,进程里面可以创建多个线程,线程是依附在进程里面的
# 线程:进程中执行代码的一个分支, cpu调度的基本单位,线程的执行顺序是无序的
#线程是程序执行的最小单位,同属一个进程的多个线程共享进程所拥有的全部资源
# 程序启动默认会有一个主线程, 程序员自己创建的线程称为子线程, 多线程可以完成多任务
#举例:进程相当于一个公司,电脑 椅子是进程分配的资源,线程就是员工
#多线程– threading模块 Thread类
# 线程类Thread参数:
# target: 执行的目标任务名
# args: 以元组的形式是给执行任务传参
# kwargs:以字典的形式是给执行任务传参
#自己定义的线程对象=threading.Thread(target=任务名)
# 方法:
#线程对象.start() 启动子线程
# setDaemon(): 守护线程
# join(): 阻塞线程
import time
import threading # 导入多线程模块
#执行的任务
# def a():
# print(“第一个任务”)
# time.sleep(2)
# print(“停顿后的任务”)
#
# def b():
# print(“第二个任务”)
# time.sleep(2)
# print(“第二个停顿的任务”)
#
# if __name__ == ‘__main__’: # 主程序入口, 规范写法
# # 3.创建子线程(实例化一个对象) # target只需要函数名
# t=threading.Thread(target=a)
# t1=threading.Thread(target=b)
# # 启动子线程
# t.start()
# t1.start()
#结果为:第一个任务
# 第二个任务 #同时打印这两个
# 停顿后的任务
# 第二个停顿的任务 #在打印这两个
#带参数的多线程任务
# def a(n):
# for i in range(n):
# print(“第一个任务”)
# time.sleep(2)
#
# def b(n):
# for i in range(n):
# print(“第二个任务”)
# time.sleep(2)
# if __name__==”__main__”:
# t=threading.Thread(target=a,args=(3,)) #args:以元组的方式给执行的任务传递参数 有多个参数一定要注意参数的顺序
# t1=threading.Thread(target=b,kwargs={“n”:2}) #keargs:以字典的方式给执行的任务传递参数 字典中键名一定要和参数名一致
# t.start()
# t1.start()
#结果为:第一个任务
# 第二个任务 #同时打印这两个
# 第一个任务
# 第二个任务 #在打印这两个
# 第一个任务 #在打印这一个
#主线程和子线程的结束顺序
# def a():
# for i in range(4):
# print(“子线程”)
# time.sleep(2)
# if __name__ ==”__main__”:
# t=threading.Thread(target=a)
# t.start()
#
# time.sleep(2)
# print(“主线程…..”)
#结果为:子线程
# 主线程…..
# 子线程
# 子线程
# 子线程
#主线程会等待所有的子线程执行结束在结束
# def a():
# for i in range(4):
# print(“子线程”)
# time.sleep(2)
# if __name__ ==”__main__”:
# #t=threading.Thread(target=a,daemon= True) #daemon= True 方法一守护线程
# t=threading.Thread(target=a)
# t.setDaemon(True ) #第二种方法守护线程 守护线程 (必须放在start前面!!!)
# t.start()
#
# time.sleep(2)
# print(“主线程…..”)
#结果为:子线程 #设置守护线程 主线程结束子线程也跟着结束
# 主线程…..
# def a():
# for i in range(4):
# print(“子线程”)
# time.sleep(2)
# if __name__ ==”__main__”:
# t = threading.Thread(target=a)
# t.setDaemon(True ) #第二种方法守护线程 守护线程 (必须放在start前面!!!)
# t.start()
# t.join() #join() 阻塞主线程有暂停的作用, 必须在start后面 等添加了join的这个子线程执行完,主线程才能继续执行
# # 调用了join方法,守护线程功能还在,只是没有体现
# time.sleep(2)
# print(“主线程…..”)
# #结果为:子线程
# 子线程
# 子线程
# 子线程
# 主线程…..
#多线程资源共享
from threading import Thread #导入多线程模块中的Thread类
# li = []
# # 写数据
# def wdata():
# for i in range(4):
# li.append(i)
# time.sleep(0.1)
# print(‘写入的数据:’, li)
#
# # 读数据
# def rdata():
# print(‘读取的数据:’, li)
#
# if __name__ == ‘__main__’:
# # wd是线程对象
# wd = Thread(target=wdata)
# rd = Thread(target=rdata)
# wd.start()
# wd.join() # 阻塞一下,等wd执行完再去执行rd
# rd.start()
#结果为:写入的数据:[0, 1, 2, 3]
# 读取的数据:[0, 1, 2, 3] #函数rdata共享了函数wdata的数据
#资源竞争
# a=0
# b=100000
# # # b的值比较小, 就没有资源竞争的问题,值比较大,计算机计算不过来, 延长时间更明显
# # 循环一次给全局变量a加1
# def jia():
# for i in range(b):
# global a # 声明全局变量
# a += 1
# print(a)
#
# # 循环一次给全局变量a加1
# def jia2():
# for i in range(b):
# global a # 声明全局变量
# a += 1
#
# print( a)
#
# if __name__ == ‘__main__’:
# f1 = Thread(target=jia)
# f2 = Thread(target=jia2)
# f1.start()
# f2.start()
#结果会因为b的值太大导致结果错乱可以用线程等待(join)和互斥锁
#互斥锁: 能够保证多个线程访问共享数据不能出现数据错误问题,对数据进行锁定
# 保证同一时刻只能有一个线程去操作
# 互斥锁是多个线程一起去抢,抢到锁的线程先执行,没有抢到锁的线程需要等待
# 使用互斥锁会影响代码的执行效率, 多任务变成了单任务执行
# 互斥锁用法
#1.创建全局互斥锁 定义互斥锁对象=Look()
#2.上锁 定义互斥锁对象.acquire()
#3.解锁 定义互斥锁对象.release() b
from threading import Thread,Lock
# a=0
# b=1000000
# lock=Lock() #创建全局互斥锁
# # # b的值比较小, 就没有资源竞争的问题,值比较大,计算机计算不过来, 延长时间更明显
# # 循环一次给全局变量a加1
# def jia():
# lock.acquire() #上锁
# for i in range(b):
# global a # 声明全局变量
# a += 1
# print(a)
# lock.release() #解锁
# # 循环一次给全局变量a加1
# def jia2():
# lock.acquire() # 上锁
# for i in range(b):
# global a # 声明全局变量
# a += 1
#
# print( a)
# lock.release() # 解锁
# if __name__ == ‘__main__’:
# f1 = Thread(target=jia)
# f2 = Thread(target=jia2)
# f1.start()
# f2.start()
#结果为:1000000
# 2000000
# 总结:
# 1.threading模块定义了Lock变量,通过调用这个函数可以获取一把互斥锁
# 2.acquire()和release()方法之间的代码同一时刻只能有一个线程去操作
# 3.acquire(加锁)和release(解锁)方法必须成对出现, 加锁的后面必须先解锁再加锁,否则会造成死锁
# 互斥锁如果没有使用好容易出现死锁的情况
# 4.死锁:一直等待对方释放锁的情况,会造成程序的停止响应,不能再处理其他任务了
# 5.同步:
# 有两个线程A和B, 线程A用来写入, 线程B读取A写入的数据。
# 线程A要先写,线程B才能读,线程A和线程B之间就是一种同步关系
# 线程同步:主线程和创建的线程之间各自执行自己的代码知道结束
转载请注明:XAMPP中文组官网 » python学习整理笔记十_多线程、多进程执行多任务