Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python线程/进程和类变量_Python_Variables_Parallel Processing - Fatal编程技术网

Python线程/进程和类变量

Python线程/进程和类变量,python,variables,parallel-processing,Python,Variables,Parallel Processing,这个问题可能真的很愚蠢,但我从今天早上开始就在编写这个代码,现在即使是愚蠢的事情也很难做到:\ 我得到了这个代码,我通过创建8个进程并运行它们来调用它。 还有一个线程必须打印关于这8个进程的信息。(代码如下) printCrackingState由我的“main”中的以下行调用: 现在的问题是:为什么要打印相同的值? 这就像t.getCurrentPin()返回\uuu init\uuuu()方法中设置的值,并且不知道我正在递增它 建议?您的问题是,您试图在一个进程中更新变量,然后在另一个进程中

这个问题可能真的很愚蠢,但我从今天早上开始就在编写这个代码,现在即使是愚蠢的事情也很难做到:\

我得到了这个代码,我通过创建8个进程并运行它们来调用它。 还有一个线程必须打印关于这8个进程的信息。(代码如下)

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