由于计算哈希值是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方法中从输入文件读取数据。
我不计算哈希值。我有两个文件,一个是我想破解的哈希,另一个是sha1哈希的破解。我正在做的是寻找2个相同的哈希值,然后编写哈希值和后面的数字进行解密。 –
而list.txt是一个散列的文件,这就是为什么我检查它是多久。然后运行线程,直到没有剩下的线(所有的线被功能检查后我会稍后添加) –
@RaslavM - 我只是想给出一个例子来说明如何处理这样的事情。当然,真正的实施取决于你。重要的是:线程不会提高你的性能。 – mata