我正在尝试制作一个哈希破解应用程序,它将检查一个行的所有行 包含 rockyou 词典中所有行的文件。在对岩石进行预哈希处理的同时 我有时间将一个哈希值检查到几秒钟,但仍然不够。这是 为什么我要将我的程序移动到多线程。但是我的线程没有出现任何异常就停止了。
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
这是输出: 当我在一段时间后运行它时,只有一个线程报告。为什么? 感谢大家的帮助
编辑:其中一个线程出现了一个关键错误。我不知道那是什么
最佳答案
由于计算哈希值是一个 CPU 绑定(bind)问题,因此在 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
关于您的线程问题:您同时从多个 thead 访问 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
我不完全确定这是你问题的原因,但它可能是,特别是如果你也在你的运行方法中读取输入文件。
关于Python:线程无故停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17513660/