Python线程/进程和类变量
这个问题可能真的很愚蠢,但我从今天早上开始就在编写这个代码,现在即使是愚蠢的事情也很难做到:\ 我得到了这个代码,我通过创建8个进程并运行它们来调用它。 还有一个线程必须打印关于这8个进程的信息。(代码如下)Python线程/进程和类变量,python,variables,parallel-processing,Python,Variables,Parallel Processing,这个问题可能真的很愚蠢,但我从今天早上开始就在编写这个代码,现在即使是愚蠢的事情也很难做到:\ 我得到了这个代码,我通过创建8个进程并运行它们来调用它。 还有一个线程必须打印关于这8个进程的信息。(代码如下) printCrackingState由我的“main”中的以下行调用: 现在的问题是:为什么要打印相同的值? 这就像t.getCurrentPin()返回\uuu init\uuuu()方法中设置的值,并且不知道我正在递增它 建议?您的问题是,您试图在一个进程中更新变量,然后在另一个进程中
printCrackingState
由我的“main”中的以下行调用:
现在的问题是:为什么要打印相同的值?
这就像t.getCurrentPin()
返回\uuu init\uuuu()
方法中设置的值,并且不知道我正在递增它
建议?您的问题是,您试图在一个进程中更新变量,然后在另一个进程中读取它。你不能那样做。与多线程相反,多处理的关键在于默认情况下不共享变量 阅读文档,尤其是和,它将解释围绕这一点的各种方法。但实际上,有两种:要么需要某种通道/API让父进程向子进程询问其当前状态,要么需要某种共享内存来存储数据。您可能需要一个锁来保护通道/共享内存 虽然共享内存似乎是这里的“明显”答案,但您可能需要对以下内容计时:
val = 0
for i in range(10000):
val += 1
val = Value('i', 0)
lock = Lock()
for i in range(10000):
with lock:
val.value += 1
值得注意的是,您的代码在线程中也可能是不正确的,尽管在CPython中它可能会工作。如果不进行任何同步,则无法保证排序。如果您在一个线程中写入一个值,然后在另一个线程中“稍后”读取它,那么您仍然可以读取旧的值。多久以后?如果线程0在内核0上运行,线程1在内核1上运行,它们的缓存中都有变量,并且没有人告诉CPU刷新缓存,那么线程1将永远继续读取旧值。实际上,CPython的全局解释器锁最终会隐式地同步所有内容(所以我们说的是毫秒而不是无穷大),并且所有变量都有显式的内存位置,而不是优化到寄存器中,等等,所以您通常可以编写无保护的竞争。但是,多亏了墨菲定律,你应该把“通常”读作“每次直到第一次向投资者演示”或“直到我们安装了带电的核反应堆”。你也可以发布调用
printCrackingState
的代码吗?我已经添加了所需的代码。好吧,第一个问题是:你确定你真的在增加它吗?尝试在运行中的循环时,在中添加打印,看看您的控制台是否收到大量打印。我打印了,它打印了正确的值!这里还有一点:对于每个实例属性,您都有一个名称相同的class属性,您从未使用过。不要这样做;这可能产生的唯一影响是造成混乱(例如,如果您在\uuuu init\uuuu
中输入错误,并且没有设置您认为已设置的实例变量,而不是明显的AttributeError
,您将得到一个混乱且难以跟踪的错误)。明白了。它使用Value
class创建共享内存。我不需要锁之类的东西,因为这些只是一些“随机”信息,告诉用户进程正在进行,还有多少剩余时间,不需要同步。@StepTNT:“不需要同步”意味着“如果读者从未看到更新的数据,则无所谓”。这显然是不正确的,因为您在这里遇到的整个问题是,读者永远看不到更新的数据……难道不需要同步来保持数据的一致性吗?(如数据库的ACID属性)。我设法让它在共享内存和无锁的情况下工作,这就是为什么我说不需要同步(我来自Java,同步是为了原子操作,这就是为什么我这么说!)@StepTNT:首先,你怎么知道你让它工作了,而不是让它在一个特定平台上的一个特定CPython版本中几乎一直工作?在多处理
的情况下,与线程化
相反,Python有效地提供了与底层操作系统共享内存API相同的保证,这通常意味着您可以获得更多,但也意味着您更难准确地知道何时可以和何时不能获得。@StepTNT:allow,我不知道您是如何学习Java的,但是Java与Python有着完全相同的问题,事实上内存模型要求它有这个问题,而且间歇性错误通常会更频繁。如果从不同步两个线程,则无法保证一个线程对(非
volatile
)变量的更改将在另一个线程中显示。(如果您已经了解Java中使用5.0+语义的volatile
的必要性,那么简短的回答是:Python没有volatile
)
def printCrackingState(threads):
info_string = '''
++++++++++++++++++++++++++++++++++
+ Starting password = s.%08d +
+--------------------------------+
+ Current pin = s.%08d +
++++++++++++++++++++++++++++++++++
+ Missing pins = %08d +
++++++++++++++++++++++++++++++++++
'''
while 1:
for t in threads:
printed_string = info_string % (t.starting_pin, t.getCurrentPin(), t.getMissingPinsCount())
sys.stdout.write(printed_string)
sys.stdout.write("--------------------------------------------------------------------")
time.sleep(30)
infoThread = threading.Thread(target = utils.printCrackingState, args=([processes]))
#infoThread = cursesTest.CursesPrinter(threads, processes, event)
infoThread.setDaemon(True)
infoThread.start()
val = 0
for i in range(10000):
val += 1
val = Value('i', 0)
lock = Lock()
for i in range(10000):
with lock:
val.value += 1