首页 > 编程语言 > 详细

python基础--GIL全局解释器锁、Event事件、信号量、死锁、递归锁

时间:2019-08-14 21:12:47      阅读:85      评论:0      收藏:0      [点我收藏+]

ps:python解释器有很多种,最常见的就是C python解释器

GIL全局解释器锁:
    GIL本质上是一把互斥锁:将并发变成串行,牺牲效率保证了数据的安全

    用来阻止同一个进程下的多个线程的同时执行(同一个进程内多个线程无法实现并行但是可以实现并发)

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

    垃圾回收机制:

        1、引用计数

        2、标记清除

        3、分代回收

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

        同时执行四个任务  计算密集型:10s

# 计算密集型
from multiprocessing import Process
from threading import Thread
#mport os,time
def work():
    res=0
    for i in range(100000000):
        res*=i


if __name__ == __main__:
    l=[]
    print(os.cpu_count())  # 本机为6核
    start=time.time()
    for i in range(6):
        # p=Process(target=work) #耗时  4.732933044433594
        p=Thread(target=work) #耗时 22.83087730407715
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop=time.time()
    print(run time is %s %(stop-start))

 

        单核情况下:

            开线程更节省资源

        多核情况下:

            开进程:10s

            开线程:40s

        同时执行四个IO密集型任务

# IO密集型
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()) #本机为6核
    start=time.time()
    for i in range(4000):
        p=Process(target=work) #耗时9.001083612442017s多,大部分时间耗费在创建进程上
        # p=Thread(target=work) #耗时2.051966667175293s多
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop=time.time()
    print(run time is %s %(stop-start))

 

        单核:开线程更省资源

        多核:开线程更省资源

    

Event事件:

    

from threading import Event,Thread
import time

# 先生成一个event对象
e = Event()


def light():
    print(红灯正亮着)
    time.sleep(3)
    e.set()  # 发信号
    print(绿灯亮了)

def car(name):
    print(%s正在等红灯%name)
    e.wait()  # 等待信号
    print(%s加油门飙车了%name)

t = Thread(target=light)
t.start()

for i in range(10):
    t = Thread(target=car,args=(伞兵%s%i,))
    t.start()

 

 

 

信号量:在不同的领域中,对应不同的知识点

    互斥锁:一个厕所(一个坑)
    信号量:公共厕所(多个坑位)

from threading import Semaphore,Thread
import time
import random


sm = Semaphore(5)  # 造了一个含有五个的坑位的公共厕所

def task(name):
    sm.acquire()
    print(%s占了一个坑位%name)
    time.sleep(random.randint(1,3))
    sm.release()

for i in range(40):
    t = Thread(target=task,args=(i,))
    t.start()

 

  

死锁:

    RLock可以被第一个抢到锁的人连续的acquire和release

    每acquire一次锁身上的计数就加1

    每release一次锁身上的计数就减1

    只要是锁的计数不为0 其他人都不能抢

class MyThread(Thread):
    def run(self):  # 创建线程自动触发run方法 run方法内调用func1 func2相当于也是自动触发
        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()

 

 

递归锁:

import threading
 
 
class MyThread(threading.Thread):
 
    def run(self):
        global n1, n2
        lock.acquire()   # 加锁
        n1 += 1
        print(self.name +  set n1 to  + str(n1))
        lock.acquire()   # 再次加锁
        n2 += n1
        print(self.name +  set n2 to  + str(n2))
        lock.release()
        lock.release()
 
n1, n2 = 0, 0
lock = threading.RLock()
 
if __name__ == __main__:
    thread_list = []
    for i in range(5):
        t = MyThread()
        t.start()
        thread_list.append(t)
    for t in thread_list:
        t.join()
    print(final num:%d ,%d % (n1, n2))

 

python基础--GIL全局解释器锁、Event事件、信号量、死锁、递归锁

原文:https://www.cnblogs.com/tulintao/p/11354459.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!