• 线程锁与死锁问题


    线程锁

    多线程修改数据会造成混乱

    from threading import Thread
    import time
    x = 0
    
    def task():
        global x
        for i in range(100000): # 最少10万级别才能看出来
            x = x+1   # 有可能右边的x刚拿到了0,
            # 发生线程不安全的原因:
            # t1 x+1 阶段 x = 0 保存了状态 cpu被切走  t2 x+1 x = 0 保存了状态 cpu被切走
            # 下次t1 继续运行代码 x = 0+1  下次t2 再运行代码的时候也是 x = 0+1
            #  也就说修改了两次 x 只加了一次1 。
            # time.sleep()
        # lock.release()
    if __name__ == '__main__':
        t_list = []
        for i in range(3):
            t = Thread(target=task)
            t_list.append(t)
            t.start()
        for i in t_list:
            i.join()
    
        print(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__':
        t_list=[]
        for i in range(3):
            t=Thread(target=task)
            t_list.append(t)
            t.start()
        for i in t_list:
            i.join()
        print(x)
    

    死锁问题

    from threading import Thread,Lock
    mutex1=Lock()
    mutex2=Lock()
    import time
    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)
    # 互相都拿到了彼此想要往下执行的必需条件,互相都不放手里的锁头.
    
    

    死锁问题解决方法

    解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。

    这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁:

    from threading import Thread,RLock
    # 递归锁 在同一个线程内可以被多次acquire
    # 如何释放 内部相当于维护了一个计数器 也就是说同一个线程 acquire了几次就要release几次
    mutex1=RLock()
    mutex2=mutex1
    import time
    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()
    
  • 相关阅读:
    开始准备AWS SysOps Administrator associate 认证考试,接下来的Blog都是准备过程中的知识点
    什么是 AWS Data Pipeline
    AWS WAF 的工作原理
    CloudTrail 的工作原理
    AngularJS尝鲜——快递运费计算
    IE UAF 漏洞(CVE-2012-4969)漏洞分析与利用
    学着分析CVE-2017-7269 -- IIS 6.0 WebDAV远程代码执行漏洞
    数据结构:实验六(单循环链表实现链式队列)
    EPS2.2 整数溢出漏洞分析到利用pwntools进行漏洞利用
    serialVersionUID作用
  • 原文地址:https://www.cnblogs.com/aden668/p/11542456.html
Copyright © 2020-2023  润新知