一、多线程的概念:
多线程指的是从软件或者硬件上实现多个线程并发执行的技术,通俗上说就是同时执行的多个任务。(同时执行多个任务就是并行,这是个伪概念,因为pycharm的运行机制决定了不可能真正实现并行)
二、什么是并发以及并行:
1.并发: 指的是任务数多余 cpu 核数,通过操作系统的各种任务调度算法
2.并行:指的是任务数小于等于 cpu 核数,即任务真的是一起执行的
三、多线程的创建:
#导包:
import threading
import time
#子线程1:
def sing():
for i in range(3):
print("正在唱歌")
#休息1s:
time.sleep(1)
#子线程2:
def dance():
for i in range(3):
print("正在跳舞")
time.sleep(1)
#主线程:
def main():
t1 = threading.Thread(target=sing)
t2 = threading.Thread(target=dance)
#当调用thread的时候,不会创建线程
#当调用thread创建出来的实例对象调用start方法的时候,才会创建线程
t1.start()
t2.start()
if __name__ == "__main__":
main()
四、线程的生命周期:
开始:当调用thread创建出来的实例对象调用start方法的时候,才会创建线程
结束:当子线程结束后,主线程才会结束。
五、如何查看线程数量:
六、函数共享全局变量:
num1 = 100
num2 = [11,22]
def text1():
global num1
num1 += 100
def text2():
num2.append(33)
print(num1)
print(num2)
text1()
text2()
print(num1)
print(num2)
输出为:
100
[11, 22]
200
[11, 22, 33]
七、多线程共享全局变量:
分为两种情况:可变型和不可变型
不可变型:整型、数字、元组------------用"global"声明变量(变量太大会出现资源竞争)
可变型:字典、列表和集合--------------用append等方法直接添加
1.不可变型:
import threading
import time
#定义一个全局变量:
gl_num = 10
#定义两个子线程:
def text1():
#global声明变量(不可变型)
global gl_num
gl_num += 1
print("此时text1的值为: %d"%gl_num)
def text2():
print("此时text2的值为: %d"%gl_num)
#定义主线程:
def main():
t1 = threading.Thread(target=text1)
t2 = threading.Thread(target=text2)
t1.start()
time.sleep()
t2.start()
time.sleep()
print("此时main的值为: %d"%gl_num)
if __name__ == "__main__":
main()
2.可变型:(args)
import threading
import time
#定义一个列表的全局变量:
num = [66,88]
#定义两个子线程:
def text1(temp): #temp:形参
#添加变量:
temp.append(99)
print("此时text1的值为: %s"%str(temp))
def text2(temp):
print("此时text2的值为: %s"str(temp))
#定义一个主线程:
def main()
t1 = threading.Tread(target = text1,args(num,)) #num:表示上面的全局变量,是个实参
t2 = threading.Tread(target = text2,args(num,))
t1.start()
time.sleep(1)
t2.start()
time.sleep(1)
if __name__ =="__main__":
main()
输出为:此时text1的值为: [66, 88, 99]
此时text2的值为: [66, 88, 99]
八、互斥锁
互斥锁概念以及产生:
用来解决多线程共享全局变量时出现的资源竞争问题。
当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制。
threading 模块中定义了 Lock 类,可以方便的处理锁定:
#1. 创建锁
mutex = threading.Lock()
# 2.锁定
mutex.acquire()
# 3.释放
mutex.release()
多线程的互斥锁
注意: 把上锁mutex.acquire()和解锁mutex.release()写在了以下代码的for里面,是以多线程修改全局变量的。若写在了for的外面就是以单线程进行修改全局变量的。
import threading
import time
#定义一个全局变量:
gl_num = 0
#创建一个互斥锁的这个类:
mutex = threading.Lock()
def text1(num):
global gl_num
for i in range(num):
# 上锁:
mutex.acquire()
gl_num += 1
#解锁:
mutex.release()
print("此时text1的值为: %d"%gl_num)
def text2(num):
global gl_num
for i in range(num):
# 上锁:
mutex.acquire()
gl_num += 1
#解锁:
mutex.release()
print("此时text2的值为: %d"%gl_num)
def main():
t1 = threading.Thread(target=text1,args=(10000000,))
t2 = threading.Thread(target=text2,args=(10000000,))
t1.start()
t2.start()
time.sleep(2)
print("此时main的值为: %d"%gl_num)
if __name__ == '__main__':
main()
九、死锁的状态(死锁是如何发生的)-----了解
死锁的状态:
当进入死锁后,2个线程互相等待对方的锁,互相占用着资源不释放。程序不报错也不执行。
避免死锁:
正确有序的分配资源;程序设计时要尽量避免(银行家算法);
添加超时时间等