zoukankan      html  css  js  c++  java
  • 线程锁

    线程锁

    from threading import Thread
    
    x = 0
    
    def task():
        global x
        for i in range(200000):
            x = x + 1
    
    if __name__ == '__main__':
        t1 = Thread(target=task)
        t2 = Thread(target=task)
        t1.start()
        t2.start()
        t1.join()
        t2.join()
        print(x)
    
    # 337204
    

    当线程t1,刚拿到x,还未进行加值和赋值操作的时候,就被CPU切走了,这时t1的x保存的是刚拿到数据的状态;然后线程t2开始加值操作,当t2被CPU切走时,x已经加了很多次了,但是t1的x还是原来的数据,然后线程t1重新开始加值操作,还是用原先x的数据,造成了数据安全的问题,

    所给线程加一把锁,以此保证数据的安全

    from threading import Thread,Lock
    
    x = 0
    mutex = Lock()
    def task:
        global x
        mutex.acquire()
        for i in range(200000):
            x = x + 1
    	mutex.release()
    
    if __name__ == '__main__':
        t1 = Thread(target=task)
        t2 = Thread(target=task)
        t1.start()
        t2.start()
        t1.join()
        t2.join()
        print(x)
    
    # 400000
    

    死锁问题

    import time
    from threading import Thread,Lock
    
    mutex1 = Lock()
    mutex2 = Lock()
    
    class MyThread(Thread):
        def run(self):
            self.task1()
            self.task2()
            
    	def task1(self):
            mutex1.acquire()
            print(f'{self.name} 抢到了锁1')
            mutex2.acquire()
            print(f'{self.name} 抢到了锁2')
            mutex2.release()
            print(f'{self.name} 释放了锁2')
            mutex1.release()
            print(f'{self.name} 释放了锁1')
            
    	def task2(self):
            mutex2.acquire()
            print(f'{self.name} 抢到了锁2')
            time.sleep(1)
            mutex1.acquire()
            print(f'{self.name} 抢到了锁1')
            mutex1.release()
            print(f'{self.name} 释放了锁1')
            mutex2.release()
            print(f'{self.name} 释放了锁2')
            
    for i in range(3):
        t = MyThread()
        t.start()
    

    线程1拿到了锁头2,想要往下执行需要锁头1,

    线程2拿到了锁头1,想要往下执行需要锁头2,

    线程1和线程2互相拿到了彼此想要往下执行的必须条件,但是互相都不放弃手里的锁头。

    递归锁

    递归锁:在同一个线程内可以被多次acquire

    如何释放:内部相当维护了一个计数器,也就是说同一个线程acquire了几次就要release几次

    import time
    from threading import Thread,RLock
    
    mutex1 = RLock()
    mutex2 = mutex1
    
    class MyThread(Thread):
        def run(self):
            self.task1()
            self.task2()
            
    	def task1(self):
            mutex1.acquire()
            print(f'{self.name} 抢到了锁1')
            mutex2.acquire()
            print(f'{self.name} 抢到了锁2')
            mutex2.release()
            print(f'{self.name} 释放了锁2')
            mutex1.release()
            print(f'{self.name} 释放了锁1')
            
    	def task2(self):
            mutex2.acquire()
            print(f'{self.name} 抢到了锁2')
            time.sleep(1)
            mutex1.acquire()
            print(f'{self.name} 抢到了锁1')
            mutex1.release()
            print(f'{self.name} 释放了锁1')
            mutex2.release()
            print(f'{self.name} 释放了锁2')
            
    for i in range(3):
        t = MyThread()
        t.start()
    

    信号量

    Semaphore管理一个内置的计数器,每当调用acquire()时内置计数器-1,调用release()时内置计数器+1;当计数器为0时,acquire()会阻塞线程,直到其他线程调用release()

    实例:同时只有5个线程可以获得semaphore,即可以限制最大的连接数为5

    import time
    from threading import Thread,Semaphore,currentThread
    
    def task():
        sm.acquire()
        print(f'{currentThread().name} 在执行')
        time.sleep(3)
        sm.release()
        
    sm = semaphore(5)
    for i in range(15):
        t = Thread(target=task)
        t.start()
    

    信号量和进程池是完全不同的概念,进程池Pool(4),最多产生4个进程,而且只有这四个进程,不会产生其他的进程,信号量是产生一堆的线程/进程。

    GIL

    GIL锁:全局解释器锁

    在CPython解释器中有一把GIL锁,GIL锁本质上是一把互斥锁。

    为什么要有GIL锁?

    因为CPython自带的垃圾回收机制不是线程完全的,所以要有GIL锁。

    影响

    这就导致了同一个进程下,同一时间只能运行一个线程,无法利用多核优势。

    同一个进程下多个线程只能实现并发不能实现并行。

    多进程vs多线程

    计算密集型,推荐使用多进程

    IO密集型,推荐使用多线程

  • 相关阅读:
    【原】泛型委托
    【原】web页面登陆验证
    【原】在一般处理程序中设置session
    16Aspx.com-PHP企业整站源码 景观石材大理石类织梦模板 含手机移动端 完整源码 APP+PC
    16Aspx.com-将15位身份证转换成18位
    16Aspx.com-书通网中小学生免费在线学习网站源码 带采集带手机版帝国cms内核
    16Aspx.com源码2014年7月详细
    Web电子商务网(三层)V2.0源码
    毫秒级百万数据分页存储过程
    C#做的一个加密/解密的类
  • 原文地址:https://www.cnblogs.com/yunluo/p/11568640.html
Copyright © 2011-2022 走看看