我试图找到这个post中描述的错误,我发现了它。
这是Singleton类,我从这个post
中提供了StackOverflow当我开始测试那个课程时,我发现,该程序会崩溃(就像在第一个链接中描述的那样)......
这是最小的例子,导致错误:
Singleton.py
import threading
class Singleton(object):
__singleton_lock = threading.Lock()
__singleton_instance = None
@classmethod
def Instance(cls):
if not cls.__singleton_instance:
with cls.__singleton_lock:
if not cls.__singleton_instance:
cls.__singleton_instance = cls()
return cls.__singleton_instance
Data.py
#-*- coding: utf-8 -*-
from singletone import Singleton
import threading
class Data(Singleton):
def __init__(self):
self.task_table = {"Zadanie1.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie2.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie3.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie4.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie5.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie6.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie7.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie8.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie9.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie10.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie11.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie12.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie13.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie14.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie15.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie16.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie17.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie18.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie19.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie20.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie21.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie22.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie23.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie24.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie25.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie26.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie27.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie28.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie29.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie30.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie31.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie32.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie33.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie34.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie35.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie36.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie37.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie38.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie39.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie40.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie41.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie42.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie43.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie44.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie45.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie46.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie47.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie48.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie49.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie50.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie51.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie52.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie53.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie54.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie55.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie56.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie57.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie58.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie59.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie60.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie61.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie62.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie63.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie64.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie65.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie66.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie67.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie68.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie69.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie70.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie71.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie72.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie73.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie74.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie75.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie76.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie77.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie78.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie79.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie80.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie81.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie82.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie83.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie84.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie85.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie86.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie87.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie88.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie89.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie90.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie91.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie92.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie93.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie94.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie95.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie96.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie97.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie98.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie99.py": {'status': 'uncomplete', 'result': '', 'time': 0}, "Zadanie100.py": {'status': 'uncomplete', 'result': '', 'time': 0}}
self.complete_task = threading.Event()
self.complete_task.set()
def getTotalCompleteTasks(self):
result = 0
for taskname in self.task_table.keys():
if self.task_table[taskname]['status'] == 'complete':
result += 1
return result
Worker.py
#-*- coding: utf-8 -*-
import threading
import subprocess
class Worker(threading.Thread):
def __init__(self, data, taskname):
self.taskname = taskname
self.data = data
threading.Thread.__init__(self)
def run(self):
self.data.complete_task.clear()
print u"Start executing %s" % self.taskname
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = subprocess.SW_HIDE
p = subprocess.Popen("C:\Python27\python.exe tasks100.5\\" + self.taskname, startupinfo=startupinfo, shell=False, stdout=subprocess.PIPE)
job_result, err = p.communicate()
print u"Stop executing %s" % self.taskname
self.data.task_table[self.taskname]['status'] = 'complete'
self.data.complete_task.set()
Agent.py
#-*- coding: utf-8 -*-
import communication_servers as cs
from worker import Worker
from data import Data
import time
app_data = Data.Instance()
SRV = cs.Server(app_data)
SRV.setDaemon(True)
SRV.start()
my_tasks = app_data.task_table.keys()[:]
while True:
print u"Complete tasks: %d\n" % app_data.getTotalCompleteTasks()
time.sleep(1)
if my_tasks:
if app_data.complete_task.is_set():
job = Worker(app_data, my_tasks.pop())
job.setDaemon(True)
print u"Running"
job.start()
else:
print u"Can't run"
print u"Test string"
Communication_server.py
#-*- coding: utf-8 -*-
import threading
import time
class Server(threading.Thread):
def __init__(self, data):
threading.Thread.__init__(self)
def run(self):
while True:
print('Server still working...\n')
time.sleep(5)
像ZadanieXX.py这样的所有文件就在那里:
import time
i = 2
p = i**400
time.sleep(5)
print p
只有减少版本的实际代码。并且它导致了在30次启动的1例中的错误。主要的while循环im. Agent.py没有迭代或迭代,但是complete_task
事件从未设置(在不到1次100次启动的情况下)。
P.S。 我尝试使用this Singleton模式,但bug仍在这里......
任何想法,为什么以这种方式工作?任何建议,如何创建单实例,线程安全类来存储所有应用程序工作数据?
我的英语不是很好。遗憾。
答案 0 :(得分:2)
请注意,使用锁定实际上不是线程安全的。在检查实例是否存在以及锁定对实例的访问权之间存在竞争条件:
def Instance(cls):
if not cls.__singleton_instance:
# another thread may succeed with the previous check again here
with cls.__singleton_lock:
if not cls.__singleton_instance:
cls.__singleton_instance = cls()
return cls.__singleton_instance
你应该交换锁的获取和__singleton_instance
的检查,因为第一次守卫后来。
请注意,在最小的工作示例中,您将显式构造Singleton,因此竞争条件永远不会触发(没有多线程实例化)。实际上,您的示例允许您在没有单例的情况下工作,因为您显式只对您的类进行一次实例化。
答案 1 :(得分:1)
很抱歉这不是关于Singleton DP的答案,但我认为你没有必要使用Singleton。
在您的示例中,Data
类仅用作数据存储,您可以使用python自己的模块Queue
进行单个数据存储。
8.10. Queue - A synchronized queue class
Queue模块实现多生产者,多消费者队列。当必须在多个线程之间安全地交换信息时,它在线程编程中特别有用。此模块中的Queue类实现了所有必需的锁定语义。这取决于Python中线程支持的可用性;参见线程模块。
是。它是线程安全的,因此您可以Queue
作为单个,居中的数据存储。
检查这样的事情。
#-*- coding: utf-8 -*-
from Queue import Queue
from threading import Thread
import time
# Set up some global variables
num_threads = 2
data_queue = Queue()
# Your Data
files = ['Zadanie1.py', 'Zadanie2.py', ... ]
def doSomething(i, q):
while True:
print '[{}] Waiting...'.format(i)
filename = q.get()
print '[{}] Working: {} '.format(i, filename)
# Do something you need
time.sleep(i + random.randint(1, 5))
q.task_done()
# Set up threads
for i in range(num_threads):
worker = Thread(target=doSomething, args=(i, data_queue,))
worker.setDaemon(True)
worker.start()
# Note that you can start threads before filling queue,
# because queue.get() will block until queue has data to return.
# Fill queue
for filename in files:
print 'Queuing: {}'.format(filename)
data_queue.put(filename)
# Wait for the queue to be empty.
data_queue.join()
print 'Done!'
结果将是这样的。
[0] Waiting...
[1] Waiting...
Queuing: Zadanie1.py
Queuing: Zadanie2.py
...
[1] Working: Zadanie1.py
[0] Working: Zadanie2.py
...
[0] Waiting...
[1] Waiting...
Done!
希望这有用!。