2013-07-07 18 views
1

我试图做一个破解应用程序,它将检查一个 文件的所有行,并且包含rockyou字典中的所有行。虽然预先哈希摇滚你 我得到的时间检查一个哈希下来几秒钟它仍然不够。这是 为什么我将我的程序移动到多线程。但是我的线程停止了,没有任何例外。Python:没有任何理由的线程停止

import threading 
import datetime 

class ThreadClass(threading.Thread): 
    hash_list=0 
    def file_len(fname): 
     with open(fname) as f: 
      for i, l in enumerate(f): 
       pass 
     return i + 1 
    list_len=file_len("list.txt") 

    def run(self): 
     while ThreadClass.list_len>0: 
      ThreadClass.list_len=ThreadClass.list_len-1 
      print str(threading.current_thread())+":"+str(ThreadClass.list_len) 
for i in range(20): 
    try: 
     t = ThreadClass() 
     t.start() 
    except: 
     raise 

这里是输出: Afther that there is only one thread printing 当我经过一段时间运行它只有一个线程报告。为什么? 感谢所有帮助

编辑:一个线程的上升的关键error.I不知道那是什么

回答

4

由于计算哈希值是CPU绑定的问题,使用多线程不会帮助你在CPython的because of the GIL

如果有任何问题,您需要使用multiprocessing。使用Pool,你的整个代码可以减少到类似:

import multiprocessing 

def calculate(line): 
    # ... calculate the hash ... 
    return (line, 'calculated_result') 

pool = multiprocessing.Pool(multiprocessing.cpu_count()) 

with open('input.txt') as inputfile: 
    result = pool.map(calculate, inputfile) 

print(result) 
# compare results 

至于你的问题与主题:你同时从多个theads访问ThreadClass.list_len。 首先访问它并将其与0进行比较。然后再次访问它,减少它并将其存回,即not thread safe 然后在打印时再次访问它。在任何这些操作之间,另一个线程可以修改该值。

为了证明这一点,我已经修改了你的代码一点点:

import threading 
import datetime 

lns = [] 
class ThreadClass(threading.Thread): 
    hash_list=0 
    list_len= 10000 

    def run(self): 
     while ThreadClass.list_len>0: 
      ThreadClass.list_len=ThreadClass.list_len-1 
      ln = ThreadClass.list_len  # copy for later use ... 
      lns.append(ln) 

threads = [] 
for i in range(20): 
    t = ThreadClass() 
    t.start() 
    threads.append(t) 

for t in threads: 
    t.join() 

print len(lns), len(set(lns)), min(lns) 

当我运行这个10倍,我得到的是:

13473 9999 -1 
10000 10000 0 
10000 10000 0 
12778 10002 -2 
10140 10000 0 
10000 10000 0 
15579 10000 -1 
10866 9996 0 
10000 10000 0 
10164 9999 -1 

所以有时它似乎运行正常,但其他人有很多已添加多次的值,而list_len甚至设法得到负值。

如果拆开的run方法,你会看到这一点:

>>> dis.dis(ThreadClass.run) 
11   0 SETUP_LOOP    57 (to 60) 
     >> 3 LOAD_GLOBAL    0 (ThreadClass) 
       6 LOAD_ATTR    1 (list_len) 
       9 LOAD_CONST    1 (0) 
      12 COMPARE_OP    4 (>) 
      15 POP_JUMP_IF_FALSE  59 

12   18 LOAD_GLOBAL    0 (ThreadClass) 
      21 LOAD_ATTR    1 (list_len) 
      24 LOAD_CONST    2 (1) 
      27 BINARY_SUBTRACT  
      28 LOAD_GLOBAL    0 (ThreadClass) 
      31 STORE_ATTR    1 (list_len) 

13   34 LOAD_GLOBAL    0 (ThreadClass) 
      37 LOAD_ATTR    1 (list_len) 
      40 STORE_FAST    1 (ln) 

14   43 LOAD_GLOBAL    2 (lns) 
      46 LOAD_ATTR    3 (append) 
      49 LOAD_FAST    1 (ln) 
      52 CALL_FUNCTION   1 
      55 POP_TOP    
      56 JUMP_ABSOLUTE   3 
     >> 59 POP_BLOCK   
     >> 60 LOAD_CONST    0 (None) 
      63 RETURN_VALUE  

简化你可以说,这些线条另一个线程可以运行和修改的东西之间。要安全地访问多个线程中的值,您需要同步访问权限。

例如使用threading.Lock的代码可以修改如下:

class ThreadClass(threading.Thread): 
    # ... 
    lock = threading.Lock() 

    def run(self): 
     while True: 
      with self.lock: 
       # code accessing shared variables inside lock 
       if ThreadClass.list_len <= 0: 
        return 
       ThreadClass.list_len -= 1 
       list_len = ThreadClass.list_len # store for later use... 
      # not accessing shared state, outside of lock 

我不能完全肯定这是你的问题的原因,但它可能是,特别是如果你还在run方法中从输入文件读取数据。

+0

我不计算哈希值。我有两个文件,一个是我想破解的哈希,另一个是sha1哈希的破解。我正在做的是寻找2个相同的哈希值,然后编写哈希值和后面的数字进行解密。 –

+0

而list.txt是一个散列的文件,这就是为什么我检查它是多久。然后运行线程,直到没有剩下的线(所有的线被功能检查后我会稍后添加) –

+0

@RaslavM - 我只是想给出一个例子来说明如何处理这样的事情。当然,真正的实施取决于你。重要的是:线程不会提高你的性能。 – mata