Python多线程Condition条件变量的理解应用
本文最后更新于 408 天前,其中的信息可能已经有所发展或是发生改变。

昨天晚上的那个例子,题目中说要用到 notify wait 可是不知为什么,昨晚没有找到相关的帖子
今天好好Google了一下,就有栗子可以学习

这是昨晚的通过互斥锁的做法:Python线程互斥锁的详细理解与应用

理解了一下,其实Condition就是在锁的基础上加入了消息通知与线程暂停,也就是说,我们可以通过通知线程恢复的方式让线程自己恢复运行与自动暂停,这样就不需要在后面的main函数中使用while True来更新线程,也就降低了CPU的使用

在运行上一个程序时,CPU的使用常在50%左右,但是新的程序由于使用了通知与休眠,这个脚本几乎不使用CPU

可以看到,旧的程序CPU使用率很高
可以看到,旧的程序CPU使用率很高
而新的程序的使用率很低
而新的程序的使用率很低

通过Condition,你可以让一个线程在运行时让另一个线程挂起,然后这个线程运行完之后通知另外一个线程恢复,这样通过结合锁的方式,就能实现复杂的线程调度

下面贴代码:

import threading
import time

# Counter类与昨天相同
class Counter():
    __Counter__ = 0
    def set(self,num):
        self.__Counter__ = num
    def get(self):
        return self.__Counter__

Counter = Counter()
# 创建一个Condition,线程需要用到
con = threading.Condition()

# 这些基础操作不详细解释
class writer(threading.Thread):
    def __init__(self,threadName,con):
        self.threadName = threadName
        self.con = con
        threading.Thread.__init__(self,name=threadName)
    def run(self):
        con = self.con
        while True:
                        # 让这个线程拿到锁
            if con.acquire():
                                # 这些操作与昨天相同
                Counter.set(Counter.get()+1)
                print ("Writer: Counter = "+str(Counter.get()))
                con.notify()
                con.release()
                                # 这个slee比较重要 下面会说到
                time.sleep(1)
            else:
                                # 此时让线程挂起等待notify与锁的释放
                con.wait()

class reader(threading.Thread):
    def __init__(self,threadName,con):
        self.threadName = threadName
        self.con = con
        threading.Thread.__init__(self,name=threadName)
    def run(self):
        con = self.con
        while True:
            if con.acquire():
                print ("Reader: Counter = "+str(Counter.get()))
                con.notify()
                con.release()
                                # 这个sleep比较重要,下面会说到
                time.sleep(1)
            else:
                con.wait()
#主函数,启动线程,不详细解释
def main():
    th_writer = writer("Writer",con)
    th_reader = reader("Reader",con)
    th_writer.start()
    th_reader.start()
if __name__ == "__main__":
    main()

运行效果跟昨天是一样的,sleep是重点需要强调下:

  • 因为我们的尝试获取锁是放在一个while True里面,所以需要给另外的线程执行时间,所以要加上sleep
  • 但是在实际应用中,往往线程时间会很长,但是只执行一次,不需要设置sleep(这时没While循环)
  • sleep一定要放在把锁放掉之后,否则会因为线程的执行时间不一样,当另外一个线程通知这个线程去拿锁的时候,这个线程却因为sleep处在休眠,而不是又Condition的wait导致的挂起(sleep属于其他阻塞状态而wait/notify属于等待阻塞)
  • 这个题目正好要没一秒打印,所以暂停时间一秒

当然你还可以通过 notifyAll 通知所以处于等待阻塞状态(也就是wait的线程)启动,但是我没用过,大家自己尝试

其实Condition内部相当于维护了一个锁和一个阻塞的线程池,锁用来控制线程访问,而线程池用于将支持wait线程的启动

这篇文章同样是讲Condition的,上面这句话就出自这里,里面的消费者问题我做了,讲的很不错值得一看:
python多线程编程(5): 条件变量同步

好的技术文章也就只能在Google上去找了。

暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇