Django会话线程安全吗?

时间:2011-11-21 12:47:45

标签: python django thread-safety python-multithreading

我将字典存储在Django会话中,该会话可由多个线程访问。所有线程都可以更新该字典,线程也从字典中获取值以运行该进程。我想知道Django Session是线程安全的还是我必须使用锁或信号量?

典型示例:

Thread1:
threadDict = request.session.get('threadDict', None)
if threadDict['stop']:
   #break the for loop exit the thread
else:
   #do some processing and update some values in thread dictionary
   threadDict['abc'] = 0
   request.session['threadDict'] = threadDict (Point1)

def someFunction():
    #this function is used to send stop signal to thread
    threadDict = request.session.get('threadDict', None)
    threadDict['stop'] = True
    request.session['threadDict'] = threadDict (Point2)

Point2更新线程词典在更新Point1之后更新它时,是否有可能更新它,然后我的stop退出线程将丢失。

更多信息

ajax请求启动四个线程,从4个不同的URL下载样本。为什么我使用线程?因为我想向用户显示当前正在下载的样本和剩下的样本。所有线程都将在会话中的字典中更新其状态。线程启动后,我每隔两秒钟发出一次ajax请求,并从会话中获取字典并读取线程的当前状态。但是这个想法失败了,因为线程独立于请求及其会话。每个ajax请求肯定都有它的会话,但是我无法将该会话传递给线程,因为当它们一旦开始时它们独立于世界的其余部分(可能是我可以通过它但我可能不会快速通过它,因为处理正在由线程)。所以要解决这个问题,我选择缓存框架而不是会话。因为缓存可以从任何地方访问。线程将它们的状态存储在字典中并重新放入缓存中,每两秒后我从缓存中获取字典并读取状态。根据我的经验,缓存还有一件事是线程安全的。因此,对于四个线程,我使用了四个字典。

5 个答案:

答案 0 :(得分:9)

对于每个请求,返回的request.session对象都是新的,访问同一个存储。此外,它们在请求时从存储器加载并在响应时保存回来。因此,如果您希望将信息从长时间运行的线程传输到另一个请求,则需要手动将其保存在长时间运行的线程中。不幸的是,这将导致修改同一会话的数据丢失。

Session在某种意义上是线程安全的。你不会以这种方式打破翻译。您的请求将在第一次访问时将会话数据视为其快照,并且在保存时它将覆盖自该时刻起落下的所有更改。因此会话状态将保持一致,但某些请求的修改可能会丢失。

实际上,这个属性对于几乎任何框架都是通用的 - 任何会话/缓存/可能在多个进程之间共享的其他存储都不太可能提供对存储在其中的对象的修改,而不会被覆盖某人的更改。

答案 1 :(得分:2)

Django会话是在请求处理开始时获取的字典,并在其末尾保存[source]。 因此,如果您对其执行并行更改,那么其中一个更改将占上风。但通常情况下,人类用户无法执行此类并行操作,业务就会继续。

现在,我不太了解您的示例,但看起来您只是在尝试滥用会话字典。我已经开发了很多基于Django的网站,我已经坚持了一些与Django本身内部的限制或错误相关的问题,但是仍然从多个线程中弄乱会话dict看起来像一个教科书的例子滥用会议..

也许我们可以在你写一些关于你想要实现的目标时找出解决方案吗?

答案 2 :(得分:0)

我不确定django是否是线程安全的。 例如,如果您使用Apache + mod_wsgi配置,每个进程有多个线程,则django / core / urlresolvers.py不是线程安全的。 但他们努力做到这一点。 django售票系统15849

上有一些票

答案 3 :(得分:-1)

由于global interpreter lock,Python中的基本类型通常是线程安全的。在某些情况下(例如在执行I / O时)释放此锁以允许其他线程访问。这意味着您(应用程序)必须在可以释放GIL的调用之间保持一致状态。此类方法的示例是阻塞套接字操作。

答案 4 :(得分:-1)

正如@Krumelur所提到的,由于全局互操作锁定(GIL),Python线程不会同时运行 - 这是一个缺陷,而不是一个功能所以不要依赖它。

目前的解决方法是使用multiprocessing module创建子流程。您可以使用Process实例的is_alive()函数检查并查看子进程是否正在运行。请参阅juicy details的文档。