基于线程和进程的深入研究
程序员文章站
2022-04-11 08:40:21
cpython中的GUL解释器锁 基于对GUL解释器锁的问题,我们先来看一下官方文档给出的解释: 这里不同于pycharm的垃圾回收机制:1.引用计数 2.标记清除 3.分代回收 也就是说,在同一进程下的多个线程是不可能实现并行的但是可以实现并发;相反多个进程下的线程是可以实现并行的。 基于这点,你 ......
cpython中的gul解释器锁
基于对gul解释器锁的问题,我们先来看一下官方文档给出的解释:
1 """ 2 3 in cpython, the global interpreter lock, or gil, is a mutex that prevents multiple 4 native threads from executing python bytecodes at once. this lock is necessary mainly 5 because cpython’s memory management is not thread-safe. (however, since the gil 6 exists, other features have grown to depend on the guarantees that it enforces.) 7 8 """ 9 我们能提炼出以下几点: 10 1.gil是一个互斥锁:保证数据的安全(以牺牲效率来换取数据的安全) 11 2.阻止同一个进程内多个线程同时执行(不能并行但是能够实现并发) 12 3.并发:看起来像同时进行的 13 4.gil全局解释器存在的原因是因为cpython解释器的内存管理不是线程安全的
这里不同于pycharm的垃圾回收机制:1.引用计数 2.标记清除 3.分代回收
也就是说,在同一进程下的多个线程是不可能实现并行的但是可以实现并发;相反多个进程下的线程是可以实现并行的。
基于这点,你会问:我曹,python连多线程抖实现不了,是不是太low了啊?我的回答是:不是的。对于多个进程的多线程的并行实现是毋庸置疑的,在同一个进程下的并行分为两种情况:
1.基于计算密集型
首先在单核情况下:基于计算的使用多线程较好,因为在相同的进程数下,多线程消耗的资源少。
在多核的情况下:开四个进程可能需要10s左右,而开四个线程需要40s左右。
2.基于io密集型
首先在单核情况下;多线程比较好一点
在多核的情况下:多线程比较好一点
1.基于计算密集型
1 # 导入相关的模块 2 from multiprocessing import process 3 from theading import thread 4 import time, os 5 6 7 # 定义计算过程 8 def work(): 9 res = 0 10 for i in range(100): 11 res *= i 12 13 if __name__=='__mian__': 14 15 # 本机的硬件基础 16 print(os.cpu_count) # 本机的cpu核心数为4 17 lis = [] 18 start = time.time() 19 for i in range(8): 20 p = process(target = work) # 创建的线程这里不做演示,类似的 21 lis.append(p) 22 p.start() 23 24 for i in lis: 25 i.join() 26 end = time.time() 27 # 打印输出使用的时间 28 print('use time is :%s' %(end - start))
2.基于io的型
from multiprocessing import process from threading import thread import os, time # def work(): # res = 0 # for i in range(100): # res += i # 基于io型 def sleep(): time.sleep(3) if __name__ == '__main__': lis = [] start = time.time() for i in range(8): p = process(target=sleep) # p = thread(target=sleep) lis.append(p) p.start() for j in lis: j.join() end = time.time() print('use time is : %s' % (end - start))
gul解释器锁和互斥锁的对比
大方面:gul解释器锁针对的是解释器;互斥锁针对的是操作的数据。
1 from threading import thread,lock 2 import time 3 4 mutex = lock() 5 6 n = 100 7 8 def task(): 9 global n 10 mutex.acquire() 11 tmp = n 12 time.sleep(0.1) 13 n = tmp - 1 14 mutex.release() 15 16 t_list = [] 17 for i in range(100): 18 t = thread(target=task) 19 t.start() 20 t_list.append(t) 21 22 for t in t_list: 23 t.join() 24 25 print(n) 26 27 """ 28 对于不同的数据,要想保证安全,需要加不同的锁处理 29 gil并不能保证数据的安全,它是对cpython解释器加锁,针对的是线程 30 保证的是同一个进程下多个线程之间的安全 31 """
死锁和递归锁
1 from threading import thread,lock,rlock 2 import time 3 4 """ 5 自定义锁一次acquire必须对应一次release,不能连续acquire 6 递归锁可以连续的acquire,每acquire一次计数加一:针对的是第一个抢到我的人 7 """ 8 import random 9 # 10 # mutexa = lock() 11 # mutexb = lock() 12 mutexa = mutexb = rlock() # 抢锁之后会有一个计数 抢一次计数加一 针对的是第一个抢到我的人 13 14 15 class mythead(thread): 16 def run(self): 17 self.func1() 18 self.func2() 19 20 def func1(self): 21 mutexa.acquire() 22 print('%s 抢到a锁了'%self.name) 23 mutexb.acquire() 24 print('%s 抢到b锁了' % self.name) 25 mutexb.release() 26 print('%s 释放了b锁'%self.name) 27 mutexa.release() 28 print('%s 释放了a锁'%self.name) 29 30 def func2(self): 31 mutexb.acquire() 32 print('%s 抢到了b锁'%self.name) 33 time.sleep(1) 34 mutexa.acquire() 35 print('%s 抢到a锁了' % self.name) 36 mutexa.release() 37 print('%s 释放了a锁' % self.name) 38 mutexb.release() 39 print('%s 释放了b锁' % self.name) 40 41 42 for i in range(100): 43 t = mythead() 44 t.start()
线程queue
import queue # 1.普通q # 2.先进后出q # 3.优先级q # queue包含的有queue,lifoqueue,priorityqueue # q=queue.queue(3) # q.put(1) # q.put(2) # q.put(3) # print(q.get()) # print(q.get()) # print(q.get()) # q = queue.lifoqueue(5) # q.put(1) # q.put(2) # q.put(3) # q.put(4) # print(q.get()) # 优先级q # q = queue.priorityqueue() # q.put((10,'a')) # q.put((-1,'b')) # q.put((100,'c')) # print(q.get()) # print(q.get()) # print(q.get())
信号量
1 from threading import thread,semaphore 2 import time 3 import random 4 sm = semaphore(5) # 五个厕所五把锁 5 # 跟你普通的互斥锁区别在于,普通的互斥锁是独立卫生间,所有人抢一把锁 6 # 信号量 公共卫生间 有多个坑,所有人抢多把锁 7 8 9 10 def task(name): 11 sm.acquire() 12 print('%s正在蹲坑'%name) 13 # 模拟蹲坑耗时 14 time.sleep(random.randint(1,5)) 15 sm.release() 16 17 18 if __name__ == '__main__': 19 for i in range(20): 20 t = thread(target=task,args=('伞兵%s号'%i,)) 21 t.start()
上一篇: 关于令元素垂直居中的总结
下一篇: python的学习之路(三)