使多个线程执行单个命令

时间:2017-12-11 15:28:00

标签: python multithreading python-multithreading

为了安全起见,我实际上正在创建一个创建虚拟文件的小脚本,用于填充磁盘(一般是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:如果你对标题有了更好的了解,我的耳朵都是开放的

1 个答案:

答案 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引用的对象中的引用计数器。