请教一个 gevent 初级问题,会有多线程问题吗?

2017-01-11 18:55:18 +08:00
 whx20202

比如我有 1000 个网址 在一个 list 里面

然后我起 10 个 gevent 协程去访问者 1000 个网址

每次取一个网址,然后把这个网址从 list 里面删除

访问完网址再去取一个

请问这样有多线程之类的安全问题吗?

4060 次点击
所在节点    Python
9 条回复
VicYu
2017-01-11 19:03:37 +08:00
虽然协程小弟办事靠谱

也是找个大哥 epoll 来搞 io

但是长者 GIL 还是保护了 list 线程安全
RadishWind
2017-01-11 19:12:50 +08:00
GIL 本身维护着一个全局锁来保证线程安全
官方解释:
In CPython, the global interpreter lock, or GIL,
is a mutex that prevents multiple native threads from executing Python bytecodes at once.
This lock is necessary mainly because CPython ’ s memory management is not thread-safe.
(However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)
tabris17
2017-01-11 19:19:21 +08:00
协程是单线程,不会有多线程同步的问题
ioiogoo
2017-01-11 22:44:36 +08:00
同一时间只有一个协程拥有运行权,不存在安全的问题
xuboying
2017-01-12 00:05:19 +08:00
为何不分配好十等分,或者用 queue
buckethead1
2017-01-12 03:08:17 +08:00
同一个时刻只有一个协程在运行
只有协程主动交出运行权,比如主动调用 gevent.sleep(),才会切换协程.
所以不会在操作 list 的时候出错

GIL 保证 bytecode 是线程安全的,比如 list.append()就是线程安全的,list[0] += 1 就不线程安全

最后 你不确定的时候就加锁吧,反正都用 Python 了
whx20202
2017-01-12 07:23:13 +08:00
@buckethead1 如果协程读数据库, gevent 会主动帮我切换吗
mengskysama
2017-01-12 21:23:46 +08:00
GIL 和这个问题是 2 个问题, http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm
使用 gevent 的时候完全可以 if len(lstA): target=lstA.pop()不需要加锁。

需要 gevent 里面使用同步试的数据库 driver 用 monkey patch 在 io 等待的时候线程交出运行权。
psjay
2017-01-12 22:27:53 +08:00
Gevent 协程只在发生 I/O 的时候进行切换,不用担心。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/333938

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX