41章
- 互斥锁
- 线程理论
- 创建线程的两种方式
- 多线程实现tcp服务端并发
- join方法
- 同一个进程下线程间数据共享
- 线程对象相关方法
- 守护线程
- GIL全局解释器锁
互斥锁
-
互斥锁定义
互斥锁是一种数据结构,使你可以执行一系列互斥操作。
-
强调
互斥锁只应该出现在多个程序操作数据的地方 其他位置尽量不要加
ps:以后我们自己处理锁的情况很少 只需要知道锁的功能即可
-
互斥锁作用
将并发变成穿行,虽然牺牲了程序的执行效率,但是保证了数据安全
-
互斥锁使用
from multiprocessing import Process, Lock
mutex = Lock()
mutex.acquire() # 抢锁
mutex.release() # 释放锁
名称 | 作用 |
---|---|
行锁 | 一锁锁一行或者多行数据 |
表锁 | 一锁锁一整张表 |
乐观锁 | 乐观锁是对于数据冲突保持一种乐观态度,操作数据时不会对操作的数据进行加锁 |
悲观锁 | 观锁是基于一种悲观的态度类来防止一切数据冲突,它是以一种预防的姿态在修改数据之前把数据锁住,然后再对数据进行读写,在它释放锁之前任何人都不能对其数据进行操作 |
线程理论
名称 | 作用 |
---|---|
进程 | 是资源单位 进程相当于是车间 进程负责给内部的线程提供相应的资源 |
线程 | 线程相当于车间的流水线,线程负责执行真正的功能 |
创建线程的两种方式
前言:
开设线程不需要完整拷贝代码 所以无论什么系统都不会出现反复操作的情况
也不需要在启动脚本中执行 但是为了兼容性和统一性 习惯在启动脚本中编写
from threading import Thread
from multiprocessing import Process
import time
----------------------------------------------
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('主线程')
---------执行结果-----------
jason正在运行
主线程
jason运行结束
------------------------------------------------------
# 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('主线程')
多线程实现TCP 服务端并发
比多进程更加简单方便,消耗的资源更少
ps:课下使用多进程或者多线程对比(任务管理器)
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()
print(money)
线程对象相关方法
1.进程号
同一个进程下开设的多个线程拥有相同的进程号
2.线程名
from threading import Thread,current_thread
current_thread().name
主:MainThread
子:Thread-N
3.进程下的线程数
active_count()
守护线程
-
定义
守护线程伴随着被守护的线程的结束而结束
from threading import Thread
import time
def task():
print('子线程运行task函数')
time.sleep(3)
print('子线程运行task结束')
GIL全局解释器锁
储备知识
1.python 解释器 也是由编程语言写出来。
Cpython 用c写出来
Jpython 用java写出来的
Pypython 用py写出来的
ps:最常用的就是Cpython(默认)
#官方文档对GIL的解释
In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)
参考群内截图 理解上述3、4解读
1.误解:python的多线程就是垃圾 利用不到多核优势
python的多线程确实无法使用多核优势 但是在IO密集型的任务下是有用的
2.误解:既然有GIL 那么以后我们写代码都不需要加互斥锁
不对 GIL只确保解释器层面数据不会错乱(垃圾回收机制)
针对程序中自己的数据应该自己加锁处理
3.所有的解释型编程语言都没办法做到同一个进程下多个线程同时执行
ps:我们平时在写代码的时候 不需要考虑GIL 只在学习和面试阶段才考虑!!!
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/279833.html