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
51300520
V2EX  ›  Python

不是说协程不用加锁吗?

  •  
  •   51300520 · 2017-09-02 00:21:52 +08:00 · 9215 次点击
    这是一个创建于 2400 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我用基于 gevent 的爬虫,如果不加锁,pymysql 的数据库操作会出错。我看很多网上教程说协程不用像线程那样加锁是优势,我还是对协程原理不是很了解, 照这样看来,写同一个文件,操作数据库,还是需要加锁的,那为什么 python 自带的 queue 在协程里面不加锁各种 get,put 也工作得很好?它是怎么做到的?
    协程和线程到底有什么区别? 都是在一个进程里面切换,不加锁都会出错
    7 条回复    2017-09-04 10:42:26 +08:00
    mlyy
        1
    mlyy  
       2017-09-02 06:49:10 +08:00 via iPhone
    coroutine 不能完全等于单线程。因为 await 本质相当于 yield,出让当前执行栈的执行权(防止阻塞)。也就是说,同一时刻内存中存在多个,不一定相互重叠的执行栈。说白了,多线程的调度是操作系统的 scheduler,而 coroutine 的调度是你的代码。
    mlyy
        2
    mlyy  
       2017-09-02 06:53:20 +08:00 via iPhone
    至于 queue 为何"正确"(undefined behavior),不如贴出你的测试代码,看看是否真的实现了 await 操作。
    NoAnyLove
        3
    NoAnyLove  
       2017-09-02 08:54:01 +08:00
    具体事情具体讨论,并没有说协程就一定不加锁,协程本身的某些功能实现也是通过线程池实现的;就算没有用到其他线程,假如一个操作需要连续性地完成,那么也是需要借助锁的概念。asyncio 和 gevent 库中都有实现 threading 下的一些同步机制,比如 Lock、Semaphore 等,虽然和 threading 的底层的实现不同,但是同样起到了保证一些操作顺序、不会被打断地执行。

    另外,queue 自带锁
    misaka19000
        4
    misaka19000  
       2017-09-02 10:41:31 +08:00
    > 协程是用户态相互协作的线程

    你看,本质上还是线程,所以还是可能存在竞争条件,所以需要加锁
    lolizeppelin
        5
    lolizeppelin  
       2017-09-02 13:56:00 +08:00   ❤️ 1
    谁和你说不用加锁的...
    oneoo
        6
    oneoo  
       2017-09-03 10:14:06 +08:00
    协程都是平等、并行的多个任务,它本身并不是多线程,每次运行的都是某个代码片段,go 是通过多线程来执行这些代码片段,才让大家误解。

    但协程的代码里面有可能会调用到底层的 C 代码,如很多库就是 C 写的,如果这个库没做好多线程的锁操作,就会出现帖子说的事。这也说明这个库实现有严重问题


    有兴趣可以去看看 OpenResty、Nginx+Lua,也是协程的世界。但这个世界里连“锁”的任何操作方法都没暴露给开发者,就是因为协程本身是不需要锁的。底层的事情就应该完整隐藏起来,这样使用者才不会遇到这种摸不着头脑的事
    oaoouo
        7
    oaoouo  
       2017-09-04 10:42:26 +08:00
    补充一下, Python 的一些数据结构是线程安全的(比如 collections 模块的 deque 结构), 使用这些结构多线程就可以不用加锁.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5810 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 06:21 · PVG 14:21 · LAX 23:21 · JFK 02:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.