Sum*_*Tea 2 c++ python multithreading gil
我现在正在使用Python实现数据订阅者,订阅数据发布者(实际上是ZeroMQ发布者套接字),并在收到任何新消息后收到通知.在我的订户中,消息在收到后被转储到数据处理器.订户完成后也会收到订户的通知.由于数据处理器是用C++编写的,因此我必须使用简单的C++模块扩展Python代码.
下面是我的数据订阅者的简化的可运行代码示例.代码main.py,其中模块proc代表处理器,订阅ZeroMQ套接字localhost:10000,设置回调,并通过调用将接收的消息发送到处理器proc.onMsg.
#!/bin/python
# main.py
import gevent
import logging
import zmq.green as zmq
import pub
import proc
logging.basicConfig( format='[%(levelname)s] %(message)s', level=logging.DEBUG )
SUB_ADDR = 'tcp://localhost:10000'
def setupMqAndReceive():
'''Setup the message queue and receive messages.
'''
ctx = zmq.Context()
sock = ctx.socket( zmq.SUB )
# add topics
sock.setsockopt_string( zmq.SUBSCRIBE, 'Hello' )
sock.connect( SUB_ADDR )
while True:
msg = sock.recv().decode( 'utf-8' )
proc.onMsg( msg )
def callback( a, b ):
print( '[callback]', a, b )
def main():
'''Entrance of the module.
'''
pub.start()
proc.setCallback( callback )
'''A simple on-liner
gevent.spawn( setupMqAndReceive ).join()
works. However, the received messages will not be
processed by the processor.
'''
gevent.spawn( setupMqAndReceive )
proc.start()
Run Code Online (Sandbox Code Playgroud)
模块proc简化,导出三个功能:
setCallback 设置回调函数,以便在处理消息时,可以通知我的订阅者;onMsg 由订户调用;start 设置一个新的工作线程来处理来自订阅者的消息,并使主线程加入以等待工作线程退出.完整版源代码可以在github上找到https://github.com/more-more-tea/python_gil.然而,它并没有像我的期望那样运行.添加处理器线程后,订户无法从gevent循环中的发布者接收数据.如果我只是丢弃数据处理器模块,则订户gevent循环可以从发布者接收消息.
代码有什么问题吗?我怀疑GIL会干扰消息处理器中pthread的并发性,或者gevent循环被饿死了.有关该问题或如何调试它的任何提示将非常感谢!
全局解释器锁本身不会阻止线程被调度.Python C API不会随处运行到pthread库中.这既好又坏.
这很好,因为您实际上可以在C或C++扩展中同时执行多项操作.
这很糟糕,因为你可能会意外违反GIL规则.
GIL的规则(大致)如下:
Py_INCREF()和引用宏等简单内容Py_DECREF().pthread_join()或者select(),这意味着你封锁了整个解释.这里指定了这些规则的正式版本.密切关注"非Python创建的线程"部分; 这正是你要做的事情.
读取代码时,看起来您无法在procThread()函数中获取GIL ,也无法在调用之前释放它pthread_join().可能还有其他问题,但对我来说这些问题最为明显.
| 归档时间: |
|
| 查看次数: |
1480 次 |
| 最近记录: |