并发编程-3
并发编程-3
目录
- 互斥锁
- 线程理论
- 创建线程的多种方式
- 线程的相关方法
- GIL全局解释锁
互斥锁
多个程序同时操作一份数据的时候很容易产生数据错乱!!!
为了避免数据错乱 我们需要使用互斥锁
-
互斥锁的作用
将并发变成串行 虽然牺牲了程序的执行效率但是保证了数据安全
-
如何使用互斥锁
from multiprocessing import Process, Lock mutex = Lock() mutex.acquire() # 抢锁 mutex.release() # 释放锁 -
互斥锁的应用场景
互斥锁只应该出现在多个程序操作数据的地方 其他位置尽量不要加
-
锁的类别
类别 用途 行锁 将一行的数据只能让一人读取 表锁 将整个表的数据只让一个人读取 乐观锁 都能查看数据,只要有一个人修改数据就放弃操作 悲观锁 只要有一个人在操作数据时就直接上锁,直到操作完才释放
线程理论
-
进程和线程
单位 理解 进程 资源单位 进程相当于是车间
进程负责给内部的线程提供相应的资源线程 执行单位 线程相当于是车间里面的流水线
线程负责执行真正的功能 -
进程与线程的关系
一个进程至少含有一个线程
同一个进程下多个线程之间资源共享
-
多进程与多线程的区别
区别 多进程 需要申请内存空间
需要拷贝全部代码 资源消耗大多线程 不需要申请内存空间
也不需要拷贝全部代码 资源消耗小
线程
-
开设线程的两种方式
from threading import Thread from multiprocessing import Process import time # def task(name): # print(f'{name}正在运行') # time.sleep(3) # print(f'{name}运行结束') """ 开设线程不需要完整拷贝代码 所以无论什么系统都不会出现反复操作的情况 也不需要在启动脚本中执行 但是为了兼容性和统一性 习惯在启动脚本中编写 """ # t = Thread(target=task, args=('jason',)) # t.start() # print('主线程') # if __name__ == '__main__': # t = Thread(target=task, args=('jason',)) # t.start() # print('主线程') class MyThread(Thread): def __init__(self, name): super().__init__() self.name = name def run(self): print(f'{self.name}正在运行') time.sleep(3) print(f'{self.name}运行结束') obj = MyThread('jason') obj.start() print('主线程') -
多线程实现TCP服务端并发
与多进程实现TCP服务端并发相比,更加方便,所消耗的资源更少
-
join方法
主线程等到子线程运行结束之后再运行 from threading import Thread import time def task(): print('正在执行') time.sleep(3) print('运行结束') t = Thread(target=task) t.start() t.join() print('主线程') -
同一个进程下线程间的数据共享
from threading import Thread money = 1000 def func(): global money money = 666 t = Thread(target=func) t.start() t.join() # 确保线程运行完毕 再查找money 结果更具有说服性 print(money) -
线程对象的相关方法
-
进程号
同一个进程下开设的多个线程拥有相同的进程号
-
线程名
from threading import Thread, current_thread current_thread().name 主:MainThread 子:Thread-N -
进程下的线程数
active_count()
-
-
守护线程
守护线程伴随着被守护的线程的结束而结束
from threading import Thread import time def task(): print('子线程运行task函数') time.sleep(3) print('子线程运行task结束') t = Thread(target=task) # t.daemon = True t.start() # t.daemon = True print('主线程') 进程下所有的非守护线程结束 主线程(主进程)才能真正结束!!!
GIL全局解释器锁
-
补充知识
python解释器也是由编程语言写出来的
Cpython 用C写出来的
Jpython 用Java写出来的
Pypython 用python写出来的
最常用的就是Cpython(默认)
-
GIL的本质
GIL的本质就是一把互斥锁
-
GIL存在的意义
-
使得同一个进程下的多个线程无法同时执行(关键)
-
cpython解释器中垃圾回收机制不是线程安全的
-
-
GIL的理解
GIL就是一把防止垃圾回收机制勿删的保护数据的互斥锁
并不能代表写代码的时候所添加的互斥锁
他们有本质上的区别,GIL是保护解释器层面的数据不会错乱
而互斥锁是自己自行添加的,对自己的数据加以保护

浙公网安备 33010602011771号