1
mlyy 2017-09-02 06:49:10 +08:00 via iPhone
coroutine 不能完全等于单线程。因为 await 本质相当于 yield,出让当前执行栈的执行权(防止阻塞)。也就是说,同一时刻内存中存在多个,不一定相互重叠的执行栈。说白了,多线程的调度是操作系统的 scheduler,而 coroutine 的调度是你的代码。
|
2
mlyy 2017-09-02 06:53:20 +08:00 via iPhone
至于 queue 为何"正确"(undefined behavior),不如贴出你的测试代码,看看是否真的实现了 await 操作。
|
3
NoAnyLove 2017-09-02 08:54:01 +08:00
具体事情具体讨论,并没有说协程就一定不加锁,协程本身的某些功能实现也是通过线程池实现的;就算没有用到其他线程,假如一个操作需要连续性地完成,那么也是需要借助锁的概念。asyncio 和 gevent 库中都有实现 threading 下的一些同步机制,比如 Lock、Semaphore 等,虽然和 threading 的底层的实现不同,但是同样起到了保证一些操作顺序、不会被打断地执行。
另外,queue 自带锁 |
4
misaka19000 2017-09-02 10:41:31 +08:00
> 协程是用户态相互协作的线程
你看,本质上还是线程,所以还是可能存在竞争条件,所以需要加锁 |
5
lolizeppelin 2017-09-02 13:56:00 +08:00 1
谁和你说不用加锁的...
|
6
oneoo 2017-09-03 10:14:06 +08:00
协程都是平等、并行的多个任务,它本身并不是多线程,每次运行的都是某个代码片段,go 是通过多线程来执行这些代码片段,才让大家误解。
但协程的代码里面有可能会调用到底层的 C 代码,如很多库就是 C 写的,如果这个库没做好多线程的锁操作,就会出现帖子说的事。这也说明这个库实现有严重问题 有兴趣可以去看看 OpenResty、Nginx+Lua,也是协程的世界。但这个世界里连“锁”的任何操作方法都没暴露给开发者,就是因为协程本身是不需要锁的。底层的事情就应该完整隐藏起来,这样使用者才不会遇到这种摸不着头脑的事 |
7
oaoouo 2017-09-04 10:42:26 +08:00
补充一下, Python 的一些数据结构是线程安全的(比如 collections 模块的 deque 结构), 使用这些结构多线程就可以不用加锁.
|