10 개의 스레드가 각각 "동시에"파일에 100 줄을 쓰는 작업이 있습니다. 나는 쓰기가 인터리브 될 것이라고 생각했다. 대신 쓰기가 동기화 된 것처럼 보입니다. 나는 GIL을 알고 있지만 기본 OS 호출이 GIL 외부에 있기 때문에 파일 I / O에 적용되지 않았다고 생각합니다.
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
. 같은 것을 원하지 않습니다 . 그래서 잠금을 도입 할 계획이지만 그 전에 실패한 테스트를 만들고 싶었습니다. 그렇게하는 데 문제가 있습니다.
관련이 있다면 Python 3.6.8에 있습니다.
또한 "쓰기가 동기화되었습니다"라는 것은 내 출력이 000001\n000002\n...000999\n
완벽한 순서 임을 의미 합니다. 적어도 나는 주문 번호 매기기를 기대할 것입니다.
문제는 쓰기가 버퍼링되므로 GIL이 실제로 해제되지 않는다는 것입니다 (일반적으로 버퍼가 가득 flush
차거나 파일이 명시 적으로 ed 또는 close
d 일 때만 발생하는 버퍼가 실제로 기록 될 때만 해제됩니다 ) . 각 스레드가 수행하는 작업은 매우 적기 때문에 시간 초과로 인해 GIL을 해제 할만큼 오래 실행되지 않으며 실제로 디스크에 기록하지 않음으로써 시스템 호출을 차단하기 때문에 해제하지 않습니다.
당신이 그것을 만들 경우 flush
각 라인 (또는이 하나의 스레드가 모든 마무리하기 전에 채운다 정도로 작은 버퍼 만들기 write
를) 예상대로 인터리빙 볼 수 있습니다. 그렇게하는 한 가지 방법은 다음과 같이 변경하는 것입니다.
with open(temp_filename, mode='a') as writer:
에:
with open(temp_filename, mode='a', buffering=1) as writer:
여기서는 buffering=1
라인 버퍼링을 의미합니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다