为了安全起见,我实际上正在创建一个创建虚拟文件的小脚本,用于填充磁盘(一般是usb密钥)。
实际上,我使用了线程模块,即使我知道如何使用它,我仍然在努力解决问题。
这里有一些代码可以解释我的问题。
import sys
if sys.version_info[0] >= 3: # Check Python's version, and dismiss Python 3
raise Exception('You must use Python 2 to launch this program')
from threading import Thread
index, running = 0, True
def main():
multiThreading()
def multiThreading():
thread1 = Thread(target=fill) # Both threads targets fill()
thread1.daemon = True
thread1.start()
thread2 = Thread(target=fill)
thread2.daemon = True
thread2.start()
while running: # Without this infinite loop, the program exits while the threads are still on, which is not really a problem in this bit of code,
# as they finish their tasks, but it is one in the original script. Anyway.
if running is False:
return None
def fill(): # this function normally fills a chosen drive with data
global index
global running
while running:
index += 1
print index
if index >= 10:
running = False
# The index is used AFTER index += 1 is executed, which causes a problem
if __name__ == '__main__':
main()
print 'End'
返回
12
34
56
78
910
End
>>>
实际上,我希望它能够打印
1
2
3
...
10
End
>>>
但是两个线程都通过索引传递,它增加了2而不是1(2因为当然有两个线程)
我尝试使用其他功能的看门狗,但结果是一样的。 此外,一次性看门狗不是解决方案,因为我想根据需要多次制作循环。
预测问题:为什么要使用多线程?因为它使文件创建更快。
你有解决方案吗?非常感谢您的阅读!
PS:请原谅我的几个英文错误,而不是我的母语:p; double-PS:如果你对标题有了更好的了解,我的耳朵都是开放的答案 0 :(得分:0)
这是因为当多个线程写入流(stdout或文件)时,它们的输出几乎肯定会混合并产生不可读的结果。你获得至少部分有序的输出主要是因为python有GIL。 (顺便说一句,我得到不同的输出。)一般情况下,当没有指定语言时,没有什么能阻止操作系统调度线程执行,例如,以下方式:
index += 1 # Thread 1
index += 1 # Thread 2
print index # Thread 2
index += 1 # Thread 2 (next iteration)
print index # Thread 1
因此,通常,当您向共享变量编写*时,您需要使用互斥锁,信号量或其他同步原语来保护该部分代码,以确保线程可以执行整个关键部分没有被打断:
from threading import Thread, Lock
index_operations_lock = Lock()
def mutlithreading():
# all the stuff you already have
thread1.join()
thread2.join()
def fill():
global index
global running
while running:
with index_operations_lock:
if index >= 10:
running = False
return
index += 1
print index
保护您有争议的资源。另请注意,此方法未指定线程执行的顺序。如果你需要从第一个线程然后从第二个线程写入,那么你需要另外两个锁或者实现生产者 - 消费者模式(即使两个线程在队列中写入,从队列中读取第三个线程并写入文件/标准输出)。
* - 在python中,赋值a = b
也是一个写入,因为这会增加b
引用的对象中的引用计数器。