zoukankan      html  css  js  c++  java
  • day30

    GIL(全局解释器锁)

    在CPython中,全局解释器锁(GIL)是一个防止多个锁的互斥锁。

    本机线程从执行Python字节码一次。这把锁主要是必须的因为CPython的内存管理不是线程安全。(然而,自从GIL存在时,其他功能已逐渐依赖于它所实施的保证。)

    基于CPython来研究全局解释器锁

    1.GIL本质是一个互斥锁

    2.GIL是为了阻止同一个进程内多个线程同时执行(并行)

    — 单个进程下的多个线程无法实现并行,但能实现并发

    3.这把锁主要是因为CPython的内存管理不是"线程安全"的

    — 内存管理

    — 垃圾回收机制

    注意:多个线程过来执行,一旦遇到IO操作,就会立马释放GIL解释器锁,交给下一个先进来的线程

    Copyimport time
    from threading import Thread, current_thread
    
    number = 100
    
    def task():
        global number
        number2 = number
        # time.sleep(1)
        number = number2 - 1
        print(number, current_thread().name)
        
    for line in range(100):
        t = Thread(target=task)
        t.start()
    

    死锁现象

    Copyfrom threading import Lock, Thread, current_thread
    import time
    
    mutex_a = Lock()
    mutex_b = Lock()
    
    
    class MyThread(Thread):
        
        # 线程执行任务
        def run(self):
            self.func1()
            self.func2()
            
        def func1(self):
            mutex_a.acquire()
            
            print(f'用户{self.name}抢到锁a')
            mutex_b.acquire()
            print(f'用户{self.name}抢到锁b')
            mutex_b.release()
            print(f'用户{self.name}释放锁b')
            mutex_a.release()
            print(f'用户{self.name}释放锁a')
            
        def func2(self):
            mutex_b.acquire()
            print(f'用户{self.name}抢到锁b')
            # IO操作
            time.sleep(1)
            
            mutex_a.acquire()
            print(f'用户{self.name}抢到锁a')
            mutex_a.release()
            print(f'用户{self.name}释放锁a')
            mutex_b.release()
            print(f'用户{self.name}释放锁b')
    
    for line in range(10):
        t = MyThread()
        t.start()
            
    Copy# 用户Thread-1抢到锁a
    # 用户Thread-1抢到锁b
    # 用户Thread-1释放锁b
    # 用户Thread-1释放锁a
    # 用户Thread-1抢到锁b
    # 用户Thread-2抢到锁a
    

    何时使用多进程或多线程?

      - 在计算密集型的情况下:
            - 使用多进程
    
        - 在IO密集型的情况下:
            - 使用多线程
        
        - 高效执行多个进程,内多个IO密集型的程序:
            - 使用 多进程 + 多线程
    

    RLock

    比喻成万能钥匙,可以提供给多个人去使用

    但是第一个使用的时候,会对该锁做一个引用计数

    只有引用计数为0,才能真正释放让另一个人去使用

    Copyfrom threading import RLock, Thread, Lock
    import time
    
    mutex_a = mutex_b = Lock()
    
    
    class MyThread(Thread):
        
        # 线程执行任务
        def run(self):
            self.func1()
            self.func2()
            
        def func1(self):
            mutex_a.acquire()
            
            print(f'用户{self.name}抢到锁a')
            mutex_b.acquire()
            print(f'用户{self.name}抢到锁b')
            mutex_b.release()
            print(f'用户{self.name}释放锁b')
            mutex_a.release()
            print(f'用户{self.name}释放锁a')
    
        def func2(self):
            mutex_b.acquire()
            print(f'用户{self.name}抢到锁b')
            # IO操作
            time.sleep(1)
            mutex_a.acquire()
            print(f'用户{self.name}抢到锁a')
            mutex_a.release()
            print(f'用户{self.name}释放锁a')
            mutex_b.release()
            print(f'用户{self.name}释放锁b')
            
    for line in range(10):
        t = MyThread()
        t.start()
        
    

    信号量

    互斥锁:比喻成一个家用马桶,同一时间只能让一个人去使用

    信号量:比喻成公厕多个马桶,同一时间可以让多个人去使用

    Copyfrom threading import Semaphore, Lock
    from threading import current_thread
    from threading import Thread
    import time
    
    sm = Semaphore(5)
    mutex = Lock()
    
    
    def task():
        # mutex.acquore()
        sm.acquire()
        print(f'{current_thread().name}执行任务')
        time.sleep(1)
        sm.release()
        # mutex.release()
        
    for line in range(20):
        t = Thread(target=task)
        t.start()
        
    

    线程队列

    线程Q(了解级别1):线程队列 (面试题):FIFO

    FIFO队列:先进先出

    LIFO队列:后进先出

    优先级队列:根据参数内,数字的大学进行分级,数字值越小,优先级越高

    Copyimport queue
    
    # 普通的线程队列: 先进先出
    # q = queue.Queue()
    # q.put(1)
    # q.put(2)
    # q.put(3)
    # print(q.get())  # 1
    
    
    # LIFO队列: 后进先出
    # q = queue.LifoQueue()
    # q.put(1)
    # q.put(2)
    # q.put(3)
    # print(q.get())  # 3
    
    # 优先级队列
    q = queue.PriorityQueue()   # 了解
    # 若参数中传的是元组,会以元组中第一个数字参数为准
    q.put(('a优', '先', '娃娃头', 4))    # a==97
    q.put(('a先', '优', '娃娃头', 3))    # a==98
    q.put(('a级', '级', '娃娃头', 2))    # a==99
    
    '''
    1.首先根据第一个参数判断ascii表的数值大小
    2.判断第一个参数中的汉字顺序
    3.再判断第二个参数中数字——》 字符串数字——》 中文
    4.以此类推
    '''
    
  • 相关阅读:
    Python3之random模块常用方法
    Go语言学习笔记(九)之数组
    Go语言学习笔记之简单的几个排序
    Go语言学习笔记(八)
    Python3之logging模块
    Go语言学习笔记(六)
    123. Best Time to Buy and Sell Stock III(js)
    122. Best Time to Buy and Sell Stock II(js)
    121. Best Time to Buy and Sell Stock(js)
    120. Triangle(js)
  • 原文地址:https://www.cnblogs.com/xwjhyy/p/11730698.html
Copyright © 2011-2022 走看看