-1

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

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

import MSCHAPV2
import threading
import binascii
import multiprocessing

class CrackerThread(multiprocessing.Process):

    password_header = "s."
    current_pin = ""
    username = ""
    server_challenge = ""
    peer_challenge = ""
    nt_response = ""
    starting_pin = 0
    limit = 0
    testing_pin = 0
    event = None

    def __init__(self, username, server_challenge, peer_challenge, nt_response, starting_pin, limit, event):
        #threading.Thread.__init__(self)
        super(CrackerThread, self).__init__()
        self.username = username
        self.server_challenge = server_challenge
        self.peer_challenge = peer_challenge
        self.nt_response = nt_response
        self.starting_pin = starting_pin
        self.limit = limit
        self.event = event
        self.testing_pin = starting_pin        
        #self.setDaemon(True)

    def run(self):        
        mschap = MSCHAPV2.MSCHAPV2()
        pin_range = self.starting_pin+self.limit
        while self.testing_pin <= pin_range and not self.event.isSet():
            self.current_pin = "%s%08d" % (self.password_header, self.testing_pin)                      
            if(mschap.CheckPassword(self.server_challenge, self.peer_challenge, self.username, self.current_pin.encode("utf-16-le"), self.nt_response)):
                self.event.set()
                print "Found valid password!"
                print "user     =", self.username
                print "password =", self.current_pin                
            self.testing_pin+=1            
        print "Thread for range (%d, %d) ended with no success." % (self.starting_pin, pin_range)

    def getCurrentPin(self):        
        return self.testing_pin

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)

printCrackingState在我的“主要”中由这些行调用:

infoThread = threading.Thread(target = utils.printCrackingState, args=([processes]))  
#infoThread = cursesTest.CursesPrinter(threads, processes, event)    
infoThread.setDaemon(True)
infoThread.start() 

现在的问题是:为什么要打印相同的值t.starting_pint.getCurrentPin()这就像t.getCurrentPin()返回__init__()方法中设置的值并且不知道我正在增加它!

建议?

4

1 回答 1

2

您的问题是您试图在一个进程中更新变量,并在另一个进程中读取它。你不能那样做。与多线程相反,多处理的全部意义在于默认情况下不共享变量。

阅读文档,尤其是在进程之间交换对象和在进程之间共享状态,它将解释解决此问题的各种方法。但实际上,有两个:要么您需要某种通道/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 的 Global Interpreter Lock 最终会隐式同步所有内容(所以我们说的是毫秒而不是无穷大),并且所有变量都有明确的内存位置,而不是被优化到寄存器中等等,所以你通常可以逃脱编写不受保护的比赛。

于 2013-03-29T18:22:32.717 回答