GIL、Event事件、信号量、死锁、递归锁

GIL全局解释器锁

Python解释器有很多种,最常见的就是CPython解释器
GIL本质也是一把互斥锁:将并发变成串行,牺牲效率保证数据的安全​
用来阻止同一个进程下的 多个线程的 同时执行
(同一个进程内的多个线程无法实现并行,但是可以实现并发)

Python的多线程没法利用多核优势,是不是就没有用了?

GIL的存在是因为CPython解释器的内存管理不是线程安全的

垃圾回收机制:
a. 引用计数
b. 标记清除
c. 分代回收

研究Python的多线程是否有用,需要分情况讨论:

(假设有四个任务,每个任务需要10s 处理完成)​

1. 计算密集型​:
单核情况下​:
​开线程更省资源(原因是开进程需要申请内存空间等操作,浪费时间)
多核情况下:
开进程处理    10s
开线程处理    40s


2. I/O密集型:
​​​​​单核情况下:
开线程更省资源(原因和计算密集型的一样)
多核情况下:
​​​开线程更省资源
​(原因是 I/O秘籍情况下,线程工作方式为 切换+保存
​进程申请内存空间,是要消耗很长时间的,
而​线程的切换+保存基本不消耗时间)
​

python的多线程到底有没有用
需要看情况而定  并且肯定是有用的
多进程+多线程配合使用​
View Code
# I/O密集型
from multiprocessing import Process
from threading import Thread
import threading
import os,time
​
def work():
    time.sleep(2)
​
if __name__ == '__main__':
    l=[]
    print(os.cpu_count())  # 本机为8核
    start=time.time()
​
    for i in range(400):
        p=Process(target=work)  # 耗时9.506524085998535s多,大部分时间耗费在创建进程上
        # p=Thread(target=work)  # 耗时 2.0459132194519043 s多
        l.append(p)
        p.start()
​
    for p in l:
        p.join()
​
    stop=time.time()
    print('run time is %s' %(stop-start))
I/O密集型
# 计算密集型
from multiprocessing import Process
from threading import Thread
import os,time
​
def work():
    res=0
    for i in range(100000000):
        res *= i
​
if __name__ == '__main__':
    l=[]
    print(os.cpu_count())  # 本机为8核
    start=time.time()
​
    for i in range(8):
        p=Process(target=work)  # 耗时  8.460614204406738s
        # p=Thread(target=work)  # 耗时 34.822699308395386s
        l.append(p)
        p.start()
​
    for p in l:
        p.join()
​
    stop=time.time()
    print('run time is %s' %(stop-start))
计算密集型

死锁

1. 代码表示下一步要acquire一个锁
2. ​但是两个线程互相拿着对方需要的锁,于是程序就hang到这儿了
这种情况就是死锁
from threading import Thread, Lock, current_thread
import time
​
mutexA = Lock()
mutexB = Lock()​​
​
class MyThread(Thread):
​
    # 创建线程自动触发run方法 run方法内调用func1 func2相当于也是自动触发
    def run(self):  
        self.func1()
        self.func2()
​
    def func1(self):
        mutexA.acquire()
        print('%s抢到了A锁'%self.name)  # self.name等价于current_thread().name
        mutexB.acquire()
        print('%s抢到了B锁'%self.name)
        mutexB.release()
        print('%s释放了B锁'%self.name)
        mutexA.release()
        print('%s释放了A锁'%self.name)
​
    def func2(self):
        mutexB.acquire()
        print('%s抢到了B锁'%self.name)
        time.sleep(1)
        mutexA.acquire()
        print('%s抢到了A锁' % self.name)
        mutexA.release()
        print('%s释放了A锁' % self.name)
        mutexB.release()
        print('%s释放了B锁' % self.name)
​
for i in range(10):
    t = MyThread()
    t.start()​​
​
'''执行结果:
Thread-1抢到了A锁
Thread-1抢到了B锁
Thread-1释放了B锁
Thread-1释放了A锁
Thread-1抢到了B锁
Thread-2抢到了A锁
​(程序到这儿并没有结束,而是一直hang着...)
​
​​​'''
死锁代码示例

猜你喜欢

转载自www.cnblogs.com/buzaiyicheng/p/11352588.html