如何在python中创建线程安全的单例

时间:2021-02-01 21:01:58

I would like to hold running threads in my Django application. Since I cannot do so in the model or in the session, I thought of holding them in a singleton. I've been checking this out for a while and haven't really found a good how-to for this.

我想在Django应用程序中保留运行的线程。由于我不能在模型中或会话中这样做,所以我想将它们保存为单例。我检查这个已经有一段时间了,还没有找到一个好的方法。

Does anyone know how to create a thread-safe singleton in python?

有谁知道如何在python中创建线程安全的singleton吗?

EDIT:

编辑:

More specifically what I wand to do is I want to implement some kind of "anytime algorithm", i.e. when a user presses a button, a response returned and a new computation begins (a new thread). I want this thread to run until the user presses the button again, and then my app will return the best solution it managed to find. to do that, i need to save somewhere the thread object - i thought of storing them in the session, what apparently i cannot do.

更具体地说,我希望实现某种“随时算法”,即当用户按下一个按钮时,返回一个响应,新的计算开始(一个新的线程)。我希望这个线程继续运行,直到用户再次按下按钮,然后我的应用程序将返回它找到的最佳解决方案。为了做到这一点,我需要在线程对象的某个地方保存—我想在会话中存储它们,显然我不能这样做。

The bottom line is - i have a FAT computation i want to do on the server side, in different threads, while the user is using my site.

底线是——当用户使用我的站点时,我想在服务器端,在不同的线程中进行大量的计算。

2 个解决方案

#1


3  

Unless you have a very good reason - you should execute the long running threads in a different process altogether, and use Celery to execute them:

除非你有很好的理由——你应该在完全不同的过程中执行长时间运行的线程,并使用芹菜来执行它们:

Celery is an open source asynchronous task queue/job queue based on distributed message passing. It is focused on real-time operation, but supports scheduling as well.

芹菜是一个基于分布式消息传递的开源异步任务队列/作业队列。它侧重于实时操作,但也支持调度。

The execution units, called tasks, are executed concurrently on one or more worker nodes using multiprocessing, Eventlet or gevent. Tasks can execute asynchronously (in the background) or synchronously (wait until ready).

执行单元称为任务,使用多处理、Eventlet或gevent在一个或多个工作节点上并发执行。任务可以异步执行(在后台)或同步执行(等待就绪)。

Celery guide for djangonauts: http://django-celery.readthedocs.org/en/latest/getting-started/first-steps-with-django.html

关于djangonauts的芹菜指南:http://django- celery.readthedocs.org/en/latest/gettingstarted/firststeps-with-django.html。

For singletons and sharing data between tasks/threads, again, unless you have a good reason, you should use the db layer (aka, models) with some caution regarding db locks and refreshing stale data.

对于单例和在任务/线程之间共享数据,除非您有很好的理由,否则您应该使用db层(即模型),并对db锁和刷新陈旧数据保持谨慎。

Update: regarding your use case, define a Computation model, with a status field. When a user starts a computation, an instance is created, and a task will start to run. The task will monitor the status field (check db once in a while). When a user clicks the button again, a view will change the status to user requested to stop, causing the task to terminate.

更新:关于您的用例,定义一个带有状态字段的计算模型。当用户启动计算时,将创建一个实例,并开始运行一个任务。任务将监视状态字段(偶尔检查db)。当用户再次单击该按钮时,视图将改变用户要求停止的状态,从而导致任务终止。

#2


1  

If you want asynchronous code in a web application then you're taking the wrong approach. You should run background tasks with a specialist task queue like Celery: http://celeryproject.org/

如果您希望在web应用程序中使用异步代码,那么您采用了错误的方法。您应该使用专业任务队列(如芹菜)运行后台任务:http://celeryproject.org/

The biggest problem you have is web server architecture. Unless you go against the recommended Django web server configuration and use a worker thread MPM, you will have no way to track your thread handles between requests as each request typically occupies its own process. This is how Apache normally works: http://httpd.apache.org/docs/2.0/mod/prefork.html

最大的问题是web服务器架构。除非您违背推荐的Django web服务器配置并使用一个工作线程MPM,否则您将无法跟踪请求之间的线程处理,因为每个请求通常都占用自己的进程。Apache通常是这样工作的:http://httpd.apache.org/docs/2.0/mod/prefork.html

EDIT:

编辑:

In light of your edit I think you might learn more by creating a custom solution that does this:

根据您的编辑,我认为您可以通过创建一个定制解决方案来了解更多:

  • Maintains start/stop state in the database
  • 维护数据库中的启动/停止状态
  • Create a new program that runs as a daemon
  • 创建一个作为守护进程运行的新程序
  • Periodically check the start/stop state and begin or end work from here
  • 定期检查启动/停止状态,从这里开始或结束工作

There's no need for multithreading here unless you need to create a new process for each user. If so, things get more complicated and using Celery will make your life much easier.

这里不需要多线程,除非您需要为每个用户创建一个新的进程。如果是这样的话,事情会变得更复杂,使用芹菜会让你的生活更轻松。

#1


3  

Unless you have a very good reason - you should execute the long running threads in a different process altogether, and use Celery to execute them:

除非你有很好的理由——你应该在完全不同的过程中执行长时间运行的线程,并使用芹菜来执行它们:

Celery is an open source asynchronous task queue/job queue based on distributed message passing. It is focused on real-time operation, but supports scheduling as well.

芹菜是一个基于分布式消息传递的开源异步任务队列/作业队列。它侧重于实时操作,但也支持调度。

The execution units, called tasks, are executed concurrently on one or more worker nodes using multiprocessing, Eventlet or gevent. Tasks can execute asynchronously (in the background) or synchronously (wait until ready).

执行单元称为任务,使用多处理、Eventlet或gevent在一个或多个工作节点上并发执行。任务可以异步执行(在后台)或同步执行(等待就绪)。

Celery guide for djangonauts: http://django-celery.readthedocs.org/en/latest/getting-started/first-steps-with-django.html

关于djangonauts的芹菜指南:http://django- celery.readthedocs.org/en/latest/gettingstarted/firststeps-with-django.html。

For singletons and sharing data between tasks/threads, again, unless you have a good reason, you should use the db layer (aka, models) with some caution regarding db locks and refreshing stale data.

对于单例和在任务/线程之间共享数据,除非您有很好的理由,否则您应该使用db层(即模型),并对db锁和刷新陈旧数据保持谨慎。

Update: regarding your use case, define a Computation model, with a status field. When a user starts a computation, an instance is created, and a task will start to run. The task will monitor the status field (check db once in a while). When a user clicks the button again, a view will change the status to user requested to stop, causing the task to terminate.

更新:关于您的用例,定义一个带有状态字段的计算模型。当用户启动计算时,将创建一个实例,并开始运行一个任务。任务将监视状态字段(偶尔检查db)。当用户再次单击该按钮时,视图将改变用户要求停止的状态,从而导致任务终止。

#2


1  

If you want asynchronous code in a web application then you're taking the wrong approach. You should run background tasks with a specialist task queue like Celery: http://celeryproject.org/

如果您希望在web应用程序中使用异步代码,那么您采用了错误的方法。您应该使用专业任务队列(如芹菜)运行后台任务:http://celeryproject.org/

The biggest problem you have is web server architecture. Unless you go against the recommended Django web server configuration and use a worker thread MPM, you will have no way to track your thread handles between requests as each request typically occupies its own process. This is how Apache normally works: http://httpd.apache.org/docs/2.0/mod/prefork.html

最大的问题是web服务器架构。除非您违背推荐的Django web服务器配置并使用一个工作线程MPM,否则您将无法跟踪请求之间的线程处理,因为每个请求通常都占用自己的进程。Apache通常是这样工作的:http://httpd.apache.org/docs/2.0/mod/prefork.html

EDIT:

编辑:

In light of your edit I think you might learn more by creating a custom solution that does this:

根据您的编辑,我认为您可以通过创建一个定制解决方案来了解更多:

  • Maintains start/stop state in the database
  • 维护数据库中的启动/停止状态
  • Create a new program that runs as a daemon
  • 创建一个作为守护进程运行的新程序
  • Periodically check the start/stop state and begin or end work from here
  • 定期检查启动/停止状态,从这里开始或结束工作

There's no need for multithreading here unless you need to create a new process for each user. If so, things get more complicated and using Celery will make your life much easier.

这里不需要多线程,除非您需要为每个用户创建一个新的进程。如果是这样的话,事情会变得更复杂,使用芹菜会让你的生活更轻松。