线程的数据传递
threading.Thread(target=函数名, args=(数据, ))
args:是一个元组 你可以将数据传递给线程执行的函数里面 传递进去的数据必须是以元组的方式传递
t1 = threading.Thread(target=send_msg, args=(userA, 99))
def send_msg(udp_socket, num):
print(num)
content = input(“你要输入的内容是>>>”)
udp_socket.sendto(content.encode(‘utf-8’), (“10.100.85.171”, 8080))
注意事项:线程执行的函数的参数个数 要和args中元素的个数要一致
资源竞争
多个线程同时操作一个共享资源时 就会出现问题 这种现状称之为线程之间的资源竞争
线程的同步来解决资源竞争问题
线程同步:表示能让多个线程安全的访问竞争资源 '互斥锁'是可以达到线程同步最简单的一个机制
互斥锁的执行逻辑: 首先会给多个线程访问的资源上一把锁(一种状态 有两种状态 1. 锁定 2. 非锁定) 当没有线程访问时 这个资源是未锁定状态 当某一个线程要去修改一个竞争资源时 会将其锁定 状态将变为锁定状态如果是锁定状态 其他线程就不能修改被锁定的资源 直到 访问的这个线程释放了资源后 状态就会变为非锁定 其他线程才会访问
这个互斥锁 保证了这个资源一次指允许有一个线程来访问
如何创建互斥锁:
1. 导入threading包
import threading/ from threading import
2. 创建互斥锁
mutex = threading.Lock() #创建所的对象
3. 在线程访问数据的时候 上锁
mutex.acquire() # 上锁函数
4. 使用完资源之后 释放资源 解锁
mutex.release()
如果互斥锁锁定的代码越少 那么执行的效率就会越高
mutex = threading.Lock()
def update():
global num
mutex.acquire()
for i in range(1000000):
num += 1
mutex.release()
print(f'update修改后的数据{num}')
def look():
global num
mutex.acquire()
for i in range(1000000):
num += 1
mutex.release()
print(f'look函数中查看的num={num}')
互斥锁的原则: 互斥锁上锁的代码越少效率就会越高
死锁
如果在一个程序中 出现了多把锁 就会出现死锁的状态
死锁: 一个线程在等待共享资源被释放 零一线程也在等待共享资源被释放 其实这个共享资源并没有被访问
一般要避免锁里面嵌套锁 或者不要睡眠时间
import threading
import time
lock1 = threading.Lock()
lock2 = threading.Lock()
class MyThread1(threading.Thread):
def run(self):
lock1.acquire()
time.sleep(1)
print('---thread1---up')
lock2.acquire()
print('-------被访问资源')
lock2.release()
lock1.release()
print('---thread--------down')
class MyThread2(threading.Thread):
def run(self):
lock2.acquire()
time.sleep(1)
print('---thread2---up')
lock1.acquire()
print('-------被访问资源')
lock1.release()
lock2.release()
print('---thread--------down')
if __name__ == '__main__':
t1 = MyThread1()
t2 = MyThread2()
t1.start()
t2.start()
进程与线程
程序: 一段静态代码的集合/ 执行后的结果 程序运行之后能被系统调度和分配资源的 叫做进程
也可以和线程做同样的操作
进程也可以多任务
使用进程实现多任务
1. 导入Process 包 这个包在multiprocessing包中
from multiprocessing import Process/ import multiprocessing
2. 创建进程
1.p1 = Process(target=函数名, args=元组)
2.p1 = multiprocessing.Process(target=函数名, args=元组)
3. 启动进程
p1.start()
import time
import multiprocessing
def sing():
for i in range(5):
print('正在唱歌..')
time.sleep(1)
def dance():
for i in range(5):
print('正在跳舞..')
time.sleep(1)
if __name__ == '__main__':
p1 = multiprocessing.Process(target=sing)
p2 = multiprocessing.Process(target=dance)
p1.start()
p2.start()
在实际开发过程中 使用线程去执行多任务会比较多一点
进程与线程之间的关系是什么
进程时程序运行之后的一个结果 线程只是进程里的一个执行单元
进程更多的是在操作系统中 去让一个程序 多开 比如QQ可以同时等多个
线程 只能在一个程序中 执行多个任务 不如说迅雷下载每下载一个资源都是一个线程 如果同时下载多个资源 那么就是多任务
线程和进程的区别:
相同点: 两者之间都可以执行多任务
不同点: 进程是一个资源 表示一个程序多次运行后的结果
线程是进程运行后在进程中的一个执行单元 专门给进程完成一个任务
线程是不能单独执行 只能依赖进程
线程和进程之间会选择 线程
在实际开发过程中 多任务的话线程会用的多一点 因为如果使用多进程的话 那么会浪费很多资源 叫做多进程单开
多开(多个进程)
并发和并行
如果你运行的程序 没有超过CPU的核数量 我们把这种状态称之为并行
否则 这种状态称之为并发