Python学习之锁、信号量、线程、队列

一、并发行与同步异步概念

      1.并发行概念

         ①并发:指系统具有处理多个任务(动作)的能力

è¿éåå¾çæè¿°

Concurrency,是并发的意思。并发的实质是一个物理CPU(也可以多个物理CPU) 在若干道程序(或线程)之间多路复用,并发性是对有限物理资源强制行使多用户共享以提高效率。
微观角度:所有的并发处理都有排队等候,唤醒,执行等这样的步骤,在微观上他们都是序列被处理的,如果是同一时刻到达的请求(或线程)也会根据优先级的不同,而先后进入队列排队等候执行。
宏观角度:多个几乎同时到达的请求(或线程)在宏观上看就像是同时在被处理。
通俗点讲,并发就是只有一个CPU资源,程序(或线程)之间要竞争得到执行机会。图中的第一个阶段,在A执行的过程中B,C不会执行,因为这段时间内这个CPU资源被A竞争到了,同理,第二个阶段只有B在执行,第三个阶段只有C在执行。其实,并发过程中,A,B,C并不是同时在进行的(微观角度)。但又是同时进行的(宏观角度)。
并行:

              ②并行:指系统具有同时处理多个任务(动作)的能力

è¿éåå¾çæè¿°

Parallelism,即并行,指两个或两个以上事件(或线程)在同一时刻发生,是真正意义上的不同事件或线程在同一时刻,在不同CPU资源呢上(多核),同时执行。
并行,不存在像并发那样竞争,等待的概念。
图中,A,B,C都在同时运行(微观,宏观)。

            ③可以说并行是并发的一个子集

        2.同步与异步

            ①同步(Sync)

所谓同步,就是发出一个功能调用时,在没有得到结果之前,该调用就不返回或继续执行后续操作。

根据这个定义,Java中所有方法都是同步调用,应为必须要等到结果后才会继续执行。我们在说同步、异步的时候,一般而言是特指那些需要其他端协作或者需要一定时间完成的任务。

简单来说,同步就是必须一件一件事做,等前一件做完了才能做下一件事。

例如:B/S模式中的表单提交,具体过程是:客户端提交请求->等待服务器处理->处理完毕返回,在这个过程中客户端(浏览器)不能做其他事。

          ②异步(Async)

异步与同步相对,当一个异步过程调用发出后,调用者在没有得到结果之前,就可以继续执行后续操作。当这个调用完成后,一般通过状态、通知和回调来通知调用者。对于异步调用,调用的返回并不受调用者控制。

对于通知调用者的三种方式,具体如下:

状态

即监听被调用者的状态(轮询),调用者需要每隔一定时间检查一次,效率会很低。

通知

当被调用者执行完成后,发出通知告知调用者,无需消耗太多性能。

回调

与通知类似,当被调用者执行完成后,会调用调用者提供的回调函数。

例如:B/S模式中的ajax请求,具体过程是:客户端发出ajax请求->服务端处理->处理完毕执行客户端回调,在客户端(浏览器)发出请求后,仍然可以做其他的事。

         ③同步和异步的区别:请求发出后,是否需要等待结果,才能继续执行其他操作。

二、 GIL的概念

         Python代码的执行由Python 虚拟机(也叫解释器主循环,CPython版本)来控制,Python 在设计之初就考虑到要在解释器的主循 环中,同时只有一个线程在执行,即在任意时刻,只有一个线程在解释器中运行。对Python 虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。
在多线程环境中,Python 虚拟机按以下方式执行:
1. 设置GIL
2. 切换到一个线程去运行
3. 运行:
    a. 指定数量的字节码指令,或者
    b. 线程主动让出控制(可以调用time.sleep(0))
4. 把线程设置为睡眠状态
5. 解锁GIL
6. 再次重复以上所有步骤

在调用外部代码(如C/C++扩展函数)的时候,GIL 将会被锁定,直到这个函数结束为止(由于在这期间没有Python 的字节码被运行,所以不会做线程切换)。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用 Python 的 threading 模块以及 queue 模块来实现生产者消费者问题的信号量解决方案。具体实现可以参考以下代码示例: ```python import threading import queue MAX_SIZE = 10 queue = queue.Queue(MAX_SIZE) # producer and consumer semaphores prod_sem = threading.Semaphore(MAX_SIZE) cons_sem = threading.Semaphore(0) class Producer(threading.Thread): def run(self): while True: # acquire producer semaphore prod_sem.acquire() item = produce_item() # add item to queue queue.put(item) print(f"Produced item: {item}") # release consumer semaphore cons_sem.release() class Consumer(threading.Thread): def run(self): while True: # acquire consumer semaphore cons_sem.acquire() item = queue.get() consume_item(item) print(f"Consumed item: {item}") # release producer semaphore prod_sem.release() # helper functions def produce_item(): # create item here return item def consume_item(item): # consume item here pass # start producer and consumer threads Producer().start() Consumer().start() ``` 该示例使用 Python 的多线程实现生产者消费者问题的信号量解决方案。生产者线程在生产一个新的商品时获取生产者信号量,将商品添加到队列中,并释放消费者信号量,表示队列中有新商品可以被消费者线程获取。消费者线程在获取新商品时获取消费者信号量,从队列中获取商品并进行消费,然后释放生产者线程信号量,表示队列中有新空间可以被生产者线程使用。这样可以保证生产者和消费者线程不会重复使用已经被生产或消费的商品或队列空间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值