пожалуйста, подумайте, когда у вас есть GIL и список, а затем манипулируйте списком в разных потоках, что произойдет?

лкивался с этим параграфом в Документации, которая говорит:

Двоичные буферизованные объекты (экземплярыBufferedReader, BufferedWriter, BufferedRandom а такжеBufferedRWPair) защитить свои внутренние конструкции с помощью замка; поэтому безопасно вызывать их из нескольких потоков одновременно.

Я не уверен, почему им нужно «защищать» свои внутренние структуры, учитывая, что GIL действует. Какая разница? Мне было все равно, пока я не узнал, что эта блокировка имеет какое-то значение, рассмотрим этот кусок кода:

from _thread import start_new_thread
import time

def start():
    for i in range(10):
        print("SPAM SPAM SPAM!")

for i in range(10):
    start_new_thread(start, ())

time.sleep(0.0001)
print("main thread exited")

Вывод при запуске на Python 3.X:

...many SPAM...
SPAM SPAM SPAM!
SPAM SPAM SPAM!
SPAM SPAM SPAM!
main thread exited
SPAM SPAM SPAM!
SPAM SPAM SPAM!
SPAM SPAM SPAM!
SPAM SPAM SPAM!
SPAM SPAM SPAM!
Fatal Python error: could not acquire lock for 
<_io.BufferedWritername='<stdout>'> at interpreter shutdown, possibly due to daemon threads

Под Python 2.7 ошибок нет. Я не знаю, почему это случилось, однако я искал вbufferedio.c, Другой код, который ведет себя аналогично приведенному выше фрагменту, который был протестирован на Python 3.X, иногда я получалFatal Python error а иногда нет. Любая резьбовая функция с петлей плюсstd[out][err].write вызывает эту фатальную ошибку. Очень трудно определить характеристики этой ошибки, и, насколько мне известно, в документации ничего не говорится о ней. Я не уверен, даже если это ошибка, я надеюсь, что нет.

Мое объяснение этого поведения выглядит следующим образом: * Я могу быть совершенно неправ: основной поток завершил работу, удерживая блокировкуsys.stdout.buffer, Однако это кажется противоречащим тому факту, что потоки завершаются, когда основной поток выходит из системы, в которой я использую Python, Linux.

Я отправляю это как ответ, это просто невозможно сделать в разделе комментариев.

Это поведение не ограничивается толькоwrite это влияетread также как иflush призывает на эти объектыBufferedReader, BufferedWriter, BufferedRandom а такжеBufferedRWPair.

1) В Linux и, возможно, также в Windows, когда основной поток завершает работу, его дочерние потоки завершаются. Как это влияет на указанное поведение? Если основной поток мог выйти во время своего временного интервала, перед переключением контекста с другим потоком, никакой фатальной ошибки не происходит, поскольку все потоки завершаются. Однако ничто не гарантирует, что основной поток завершит работу сразу после запуска.

2) Неустранимая ошибка имеет место между процессом завершения (выключением) интерпретатора иread, write, или жеflush вызов и, возможно, другие операции наBuffered* объект. Процесс завершения получает блокировку этих объектов, любойwrite например кBufferedWriter результат объекта вFatal Python error.

os._exit завершает работу интерпретатора без выполнения шагов завершения, и, следовательно, интерпретатор не будет владеть блокировкой объекта, о котором мы говорим, это еще один пример:

from _thread import start_new_thread
import time, sys, os

def start(myId):
    for i in range(10):
        sys.stdout.buffer.write(b"SPAM\n")

for i in range(2):
    start_new_thread(start, (i,))

x = print("main thread")
print(x)

#os._exit(0)

В приведенном выше коде, если основной поток завершает работу сразу после запуска, вот и все, никакой фатальной ошибки не происходит, и все порожденные потоки завершаются немедленно (по крайней мере, в Linux), хотя это зависит от платформы. Если вам не повезло, и другой поток начал играть на поле до выхода из основных потоков, безos._exit(0) вызов интерпретатора проходит свой обычный цикл завершения, чтобы получить блокировкуsys.stdout.buffer что приводит к фатальной ошибке. Запустите этот код несколько раз, чтобы заметить его различное поведение.

Ответы на вопрос(0)

Ваш ответ на вопрос