zoukankan      html  css  js  c++  java
  • 多线程并发--竞争问题

    前言:GIL

    GIL的全称是Global Interpreter Lock(全局解释器锁),来源是python设计之初的考虑,为了数据安全所做的决定。某个线程想要执行,必须先拿到GIL,我们可以把GIL看作是“通行证”,并且在一个python进程中,GIL只有一个。拿不到通行证的线程,就不允许进入CPU执行。GIL只在cpython中才有,因为cpython调用的是c语言的原生线程,所以他不能直接操作cpu,只能利用GIL保证同一时间只能有一个线程拿到数据。而在pypy和jpython中是没有GIL的。

    在python中多线程的并发只能每一刻执行一个线程,那么就会产生一个竞争资源问题,线程是共享数据的。

    在这用力扣的题目解释用同步锁机制解决竞争条件

    假设有一个方法 withdraw(amount),如果请求量小于当前余额,则从当前余额中减去请求量,然后返回余额。方法定义如下:

    1 balance = 500
    2 def withdraw(amount):
    3     if (amount < balance):
    4         balance -= amount
    5     return balance

    正常结果余额不能为负。但此时我用两个线程不同参数执行该方法时,如:线程1 withdraw(400)和线程2 withdraw(200)的执行流程如下图:

     对于这种问题,我们可以利用锁来解决,将一个线程的关键执行部分加上锁,执行完在释放。如下图

     在3、4步的时候,线程2执行到来关键部分所以加上来锁,因此线程1此时处于休眠状态,5、6步的时候同理。

    例题:--同步锁

    三个不同的线程将会共用一个 Foo 实例。

    线程 A 将会调用 one() 方法
    线程 B 将会调用 two() 方法
    线程 C 将会调用 three() 方法
    请设计修改程序,以确保 two() 方法在 one() 方法之后被执行,three() 方法在 two() 方法之后被执行。

    思路:利用依赖关系,创建一个变量firstJobDone协调one()和two()之间的执行顺序,在创建一个变量secondJobDone协调two()和three()之间的执行关系

    • 首先初始化共享变量 firstJobDone 和 secondJobDone,初始值表示所有方法未执行。
    • 方法 first() 没有依赖关系,可以直接执行。在方法最后更新变量 firstJobDone 表示该方法执行完成。
    • 方法 second() 中,检查 firstJobDone 的状态。如果未更新则进入等待状态,否则执行方法 second()。在方法末尾,更新变量 secondJobDone 表示方法 second() 执行完成。
    • 方法 third() 中,检查 secondJobDone 的状态。与方法 second() 类似,执行 third() 之前,需要先等待 secondJobDone 的状态。
    from threading import Lock
    
    class Foo:
        def __init__(self):
            self.firstjobDone = Lock()
            self.secondjobDone = Lock()
            self.firstjobDone.acquire()   # 请求加锁
            self.secondjobDone.acquire()
    
    
        def first(self, printFirst: 'Callable[[], None]') -> None:
            
            # printFirst() outputs "first". Do not change or remove this line.
            printFirst()
            self.firstjobDone.release()   # 释放锁
    
    
        def second(self, printSecond: 'Callable[[], None]') -> None:
            
            # printSecond() outputs "second". Do not change or remove this line.
            with self.firstjobDone:    # 上下文管理器,可获取和释放锁
                printSecond()
                self.secondjobDone.release()
    
    
        def third(self, printThird: 'Callable[[], None]') -> None:
            
            # printThird() outputs "third". Do not change or remove this line.
            with self.secondjobDone:
                printThird()

    题目出处:https://leetcode-cn.com/problems/print-in-order/

  • 相关阅读:
    DEDECMS里面DEDE函数解析
    dede数据库类使用方法 $dsql
    DEDE数据库语句 DEDESQL命令批量替换 SQL执行语句
    织梦DedeCms网站更换域名后文章图片路径批量修改
    DSP using MATLAB 示例 Example3.12
    DSP using MATLAB 示例 Example3.11
    DSP using MATLAB 示例 Example3.10
    DSP using MATLAB 示例Example3.9
    DSP using MATLAB 示例Example3.8
    DSP using MATLAB 示例Example3.7
  • 原文地址:https://www.cnblogs.com/leisunny/p/13469657.html
Copyright © 2011-2022 走看看