另一个问题中的一些讨论鼓励我更好地理解多线程Python程序中需要锁定的情况.
每本文章在Python线程,我有当多个线程同时访问共享的状态可能出现的缺陷的几个实体,可测试的例子.此页面上提供的示例竞争条件涉及读取和操作存储在字典中的共享变量的线程之间的竞争.我认为这场比赛的情况非常明显,幸运的是,这是非常值得考验的.
但是,我无法通过列表追加或变量增量等原子操作来唤起竞争条件.这个测试详尽地试图展示这样一个种族:
from threading import Thread, Lock
import operator
def contains_all_ints(l, n):
l.sort()
for i in xrange(0, n):
if l[i] != i:
return False
return True
def test(ntests):
results = []
threads = []
def lockless_append(i):
results.append(i)
for i in xrange(0, ntests):
threads.append(Thread(target=lockless_append, args=(i,)))
threads[i].start()
for i in xrange(0, ntests):
threads[i].join()
if len(results) != ntests or not contains_all_ints(results, ntests):
return False
else:
return True
for i in range(0,100):
if test(100000):
print "OK", i
else:
print "appending to …Run Code Online (Sandbox Code Playgroud) 我正在使用SWIG将第三方C++包集成到python应用程序中.该程序包通过网络连接到专有API并接收更新.整个流程是python实例化一个C++对象,调用它的函数来设置它,然后等待更新.
我使用SWIG的director功能为更新实现了一个回调机制,并且在从python或python调用的C++函数进行测试时,它运行良好.也就是说,我能够在Python中继承C++类,从C++调用它的虚函数,并看到python代码优先并执行.
问题:
当我从网络收到更新时,我得到:
The thread 'Win32 Thread' (0x1f78) has exited with code 0 (0x0).
Unhandled exception at 0x1e0650cb in python.exe: 0xC0000005: Access violation writing location 0x0000000c.
Run Code Online (Sandbox Code Playgroud)
python27.dll调用回调函数时会从内部抛出此异常.
我怀疑是这样的: 我违反了GIL
AFAIU更新来自不同的线程并使用该线程调用python的代码.
在这一点上,我很茫然.SWIG的导演功能是否仅限于在python中启动的流程(即来自python托管线程)?
我该如何规避这个?如何引导从C++到python的更新?甚至可以使用SWIG吗?
我应该采用完全不同的方法吗?
我愿意接受有关此事的任何建议......
我现在已经阅读了几个小时,我可以完全弄清楚python多线程如何比单个线程更快.
这个问题真的源于GIL.如果有GIL,并且任何时候只有一个线程真正运行,那么多线程如何比单个线程更快?
我读到了GIL发布的一些操作(比如写入文件).是什么让多线程更快?
关于greenlets.这些如何帮助并发?到目前为止,我看到的所有目的都是在功能和较简单的屈服功能之间轻松切换.
编辑:世界上像Tornado这样的服务器如何处理成千上万的同时连接?
假设我写了一个wsgi application.我上运行此应用程序Apache2的Linux多线程mod-wsgi配置,让我的应用程序在每一个进程的多个线程运行:
WSGIDaemonProcess mysite processes=3 threads=2 display-name=mod_wsgi
WSGIProcessGroup mysite
WSGIScriptAlias / /some/path/wsgi.py
Run Code Online (Sandbox Code Playgroud)
应用程序代码是:
def application(environ, start_response):
from foo import racer
status = '200 OK'
response_headers = [('Content-type', 'text/plain')]
start_response(status, response_headers)
return [racer()] #call to racer creates a race condition?
Run Code Online (Sandbox Code Playgroud)
模块foo.py:
a = 1
def racer():
global a
a = a + 1
return str(a)
Run Code Online (Sandbox Code Playgroud)
我只是用变量创建了一个竞争条件a吗?我想,a是一个模块级变量,它存在于foo.py线程中并且是相同的(共享的)?
从中得出更多的理论问题:
a变量,所以我的例子不是线程安全的?Apache,Linux上我的应用程序的每个线程都是用C语言创建的pthreadsAPI和函数,pthread必须执行的是某种python解释器的主要功能?或者Apache是否以某种方式保护我免受此错误的影响?我已经在大型C ++应用程序中嵌入了Python3。Python提供了用于自定义数据处理的用户脚本功能。
问题:我有许多与Python交互的线程,但是我真的不知道如何使用GIL保护我的代码。到目前为止,使代码工作的唯一方法是使用boost::mutex。
这是一个非常简化的示例,重现了我的问题:
Init()以初始化Python(静态函数)。Pythonize()在Python上做一些工作。第一次锁定GIL时,线程B被阻塞。代码:
#include <iostream>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include "Python.h"
struct RTMaps_GILLock
{
RTMaps_GILLock()
{
std::cout << "Locking..." << std::endl;
m_state = PyGILState_Ensure();
}
~RTMaps_GILLock()
{
std::cout << "Unlocking..." << std::endl;
PyGILState_Release(m_state);
}
private:
PyGILState_STATE m_state;
};
#define GILLOCK RTMaps_GILLock lock;
class PythonEmbed
{
public:
static void Init()
{
Py_Initialize();
// EDIT : adding those two lines made my day :
PyEval_InitThreads(); // This acquires GIL
PyEval_SaveThread(); …Run Code Online (Sandbox Code Playgroud) 我在迭代过程中遇到错误'RuntimeError:字典改变了大小',同时迭代了一个线程中的字典,该字符被插入到Python 2.7中的另一个线程中.我发现通过使用Global Intrepreter Lock,我们可以在mutithreaded情境中锁定一个对象.
In thread1:
dictDemo[callid]=val
in thread2:
for key in dictDemo:
if key in dictDemo:
dictDemo.pop(key,None)
Run Code Online (Sandbox Code Playgroud)
我在thread2中遇到错误'RuntimeError:字典在迭代期间改变了大小',因为thread1在同一时间工作.**如何使用GIL来锁定thread2中的dictDemo字典?**或者GIL只能用于线程?或者有没有办法锁定字典,以便一次限制2个线程使用对象?
假设我有一个线程和程序的主要部分.因为GIL,一个线程应该在正确的时间(而不是同时)工作?但是,如果其中一个线程是无限循环(或两者都是这样)呢?
这两个过程会并行运行吗?
def test():
while True:
print "hello"
def test2():
while True:
print "hi"
def start_thread():
try:
thread.start_new_thread( test2,() )
except:
print "Error: Unable to start thread"
start_thread()
test()
Run Code Online (Sandbox Code Playgroud) 假设我有一个numpy数组a,我想创建一个新的数组,b这
b[i, j]是一个函数,比如说:
a[i-1, j-1], a[i-1, j ], a[i-1, j+1],
a[i , j-1], a[i , j ], a[i , j+1],
a[i+1, j-1], a[i+1, j ], a[i+1, j+1]
Run Code Online (Sandbox Code Playgroud)
最快的方法是什么?
由于这是一个可分离的过滤器,有没有办法在多个线程中运行它?(不是进程,因为我必须将数据复制回来)
或者正在编写C代码以绕过GIL强制执行?
部分解决方案(如假设功能是线性的)也是受欢迎的.
我正试着与同事解决争执.假设我有一个psycopg2用于与Postgres数据库通信的Python 2.6应用程序.该应用程序是多线程的.当一个线程使用数据库调用时psycopg2,是否会释放GIL,以便其他线程也可以进行数据库调用?
我一遍又一遍地阅读“Luciano Ramalho”的“Fluent Python”,但我无法理解 asyncio.sleep 在 asyncio 中的行为。
书中有一段说:
永远不要在 asyncio 协程中使用 time.sleep 除非你想阻塞主线程,从而冻结事件循环和整个应用程序。(...) 它应该从 asyncio.sleep(DELAY) 产生。
另一方面:
Python 标准库中的每个阻塞 I/O 函数都会释放 GIL (...) time.sleep() 函数也释放 GIL。
随着 time.sleep() 释放 GIL 代码,其他线程可以运行,但会阻塞当前线程。由于 asyncio 是单线程的,我知道 time.sleep 会阻塞 asyncio 循环。
但是, asyncio.sleep() 如何不阻塞线程?是否可以不延迟事件循环并同时等待?
gil ×10
python ×9
c++ ×2
arrays ×1
concurrency ×1
dictionary ×1
django ×1
greenlets ×1
numpy ×1
postgresql ×1
python-3.x ×1
python-c-api ×1
swig ×1
wsgi ×1