让多个线程执行一个命令

Make multiple threads exec a single command

我实际上正在编写一个创建虚拟文件的小脚本,用于填充磁盘(一般是 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'

哪个returns

12

34

56

78

910

End
>>> 

事实上,我想让它打印出来

1

2

3

...

10

End
>>>

但是两个线程都通过索引,它加 2 而不是 1(2 因为当然有两个线程)

我试过看门狗,其他功能,但结果是一样的。 而且,one-time 看门狗也不是解决方案,因为我想根据需要多次循环。

预测题:为什么要用multi-threads?因为它使文件创建速度更快。

你有解决办法吗?非常感谢阅读!

PS: 请原谅我的一些英语错误,不是我的母语:p ; double-PS: 如果你对标题有更好的想法,我的耳朵都打开了

这是因为当多个线程写入流(stdout 或文件)时,它们的输出几乎肯定会混合并产生不可读的结果。你得到至少部分有序的输出主要是因为 python 有 GIL。 (顺便说一句,我得到不同的输出。)在一般情况下,当未指定语言时,没有什么可以阻止 OS 以以下方式调度线程执行:

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.

引用的对象中的引用计数器