社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

多线程python访问似乎是同步的

Pace • 5 年前 • 1588 次点击  

我有一个任务,10个线程每个线程“同时”向一个文件写入100行。我原以为这些字会交错排列相反,写操作似乎是同步的我知道GIL,但我不认为它适用于文件I/O,因为底层OS调用不在GIL之外。

import threading
import tempfile

with tempfile.NamedTemporaryFile(delete=False) as named_temp:

    temp_filename = named_temp.name
    print(temp_filename)

    with open(temp_filename, mode='a') as writer:

        def thread_task(writer, thread_index):
            for iter_index in range(0, 100):
                writer.write(f'{(iter_index + thread_index * 100):06}')
                writer.write('\n')

        def make_thread(writer, thread_index):
            return threading.Thread(target=lambda: thread_task(writer, thread_index))

        threads = []
        for thread_index in range(0, 10):
            threads.append(make_thread(writer, thread_index))

        for thread in threads:
            thread.start()
        for thread in threads:
            thread.join()

    with open(temp_filename, mode='r+') as reader:
        for line in reader.readlines():
            print(line, end='')

这是意料之中的,还是我设置的不正确?我担心上面的代码交错输出(我不介意行的顺序,但不希望像 000007000008\n\n 是的。所以我计划引入锁,但在我这么做之前,我想创建一个失败的测试,我很难这样做。

这是在Python3.6.8上,如果相关的话。

另外,我的意思是我的输出是 000001\n000002\n...000999\n 井然有序至少我会预料到编号有问题。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/48345
 
1588 次点击  
文章 [ 1 ]  |  最新文章 5 年前
ShadowRanger
Reply   •   1 楼
ShadowRanger    5 年前

问题是写操作是被缓冲的,所以gil实际上并没有被释放(它只在缓冲区实际被写出来时才被释放,通常只有在缓冲区已满或文件显式地 flush ED或 close d)由于每个线程所做的工作非常少,它们永远不会运行足够长的时间来释放gil,因为超时,并且永远不会真正写入磁盘,它们永远不会因为开始阻塞系统调用而释放gil。

如果你成功了 脸红 对于每一行(或者使缓冲区足够小,以至于在完成所有的 write s),您将看到预期的交错。一种方法是改变:

with open(temp_filename, mode='a') as writer:

致:

with open(temp_filename, mode='a', buffering=1) as writer:

在哪里? buffering=1 表示缓存线。