V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
AILOVEU
V2EX  ›  Python

[多线程] Python 多线程的锁为什么不好用?

  •  
  •   AILOVEU · 2019-07-02 10:08:25 +08:00 · 3133 次点击
    这是一个创建于 1978 天前的主题,其中的信息可能已经有所发展或是发生改变。

    各位看官不要纠结这段代码的作用。。。 这段代码中有两个注释,加注释和不加注释为什么不一样?

    
    import threading
    import time
    def  producer():
        while True:
            time.sleep(0.2)
            lock.acquire()
            print('producer acquire lock')
            time.sleep(0.1)
            time.sleep(0.1)
            print('producer release lock')
            lock.release()
    
    def consumer():
        while True:
            time.sleep(0.1)
            #lock.acquire()
            print('consumer eating')
            #lock.release()
    if __name__ == "__main__":
        lock = threading.RLock()
        t1 = threading.Thread(target=producer, args=())
        t2 = threading.Thread(target=consumer, args=())
        t1.start()
        t2.start()
        t1.join()
        t2.join()
    

    加注释运行结果:

    
    consumer eating
    producer acquire lock
    consumer eating
    consumer eating
    producer release lock
    consumer eating
    consumer eating
    producer acquire lock
    

    不加注释运行结果:

    
    consumer eating
    producer acquire lock
    producer release lock
    consumer eating
    consumer eating
    producer acquire lock
    producer release lock
    

    我觉得加不加注释都应该是 “不加注释运行结果”,

    即 producer 获取 lock 后,没有释放前,consumer 为什么还运行

    第 1 条附言  ·  2019-07-02 11:06:51 +08:00

    lock不阻塞线程吗?

    12 条回复    2019-07-03 18:33:34 +08:00
    lihongjie0209
        1
    lihongjie0209  
       2019-07-02 10:19:06 +08:00
    这段代码也是牛逼, 所有入口持有一把锁, 不管你几个线程都只能串行, 线程越多性能越差
    fuxiuyin
        2
    fuxiuyin  
       2019-07-02 10:30:31 +08:00
    加注释的话,consumer 运行又没有任何限制,为啥要等 producer 释放锁呀。
    ilyh
        3
    ilyh  
       2019-07-02 10:31:50 +08:00
    没毛病啊, 不加注释:consumer 先获取到锁, 然后 producer 再获取到锁,
    geelaw
        4
    geelaw  
       2019-07-02 10:35:34 +08:00 via iPhone
    我假设你说的“不加注释”的意思是“不注释掉 consumer 拿锁的两行”。

    成语:掩耳盗铃。
    krixaar
        5
    krixaar  
       2019-07-02 10:48:42 +08:00
    加注释:consumer 的运行和 lock 这个锁无关,因此 consumer 的运行和 lock 这个锁无关。

    不加注释:consumer 的运行受到 lock 这个锁的限制,因此 consumer 的运行受到 lock 这个锁的限制。

    综上:尼克杨问号.jpg
    Gakho
        6
    Gakho  
       2019-07-02 11:24:02 +08:00
    不太明白,LZ 是想要 Barrier 或者 Condition 的功能?
    Trim21
        7
    Trim21  
       2019-07-02 11:27:44 +08:00 via iPhone
    消费者和生产者用的同一把锁,不注释的情况下,生产者锁没释放消费者拿不到,肯定在 acqure 和 release 之间不会 eat 啊
    wevsty
        8
    wevsty  
       2019-07-02 11:31:34 +08:00
    threading.RLock() 只会导致在已经被加锁的情况下再 lock 同一个锁的时候才会阻塞试图 lock 的线程。
    decemberpei
        9
    decemberpei  
       2019-07-02 11:46:51 +08:00 via iPhone   ❤️ 2
    楼主对 lock 理解有误。lock 的意思是,如果 A 拿到了 lock,这个时候如果 B 也尝试拿,那么 B 就会被 block 住,直到 A 释放了 lock,B 才能拿到 lock 并恢复运行。
    加了注释的情况下,B 根本没用尝试拿 lock,当然不会被 block 住,
    krixaar
        10
    krixaar  
       2019-07-02 11:47:05 +08:00
    > lock 不阻塞线程吗?

    阻塞线程的是 lock.acquire()这一句,注释掉之后就不阻塞了,因为代码里都没提到 lock。
    weyou
        11
    weyou  
       2019-07-02 13:19:36 +08:00 via Android
    @lihongjie0209 实际应用中只会对临界资源加锁,这只是一个多线程锁的例子,没毛病。
    zkqiang
        12
    zkqiang  
       2019-07-03 18:33:34 +08:00
    加了注释 consumer 肯定无限循环啊,都跟 lock 没关系了,为啥会跟不加注释一样呢?
    好奇楼主咋想的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2785 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 12:48 · PVG 20:48 · LAX 04:48 · JFK 07:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.