В одном из сообщений в блоге Тимми Хосе на https://z0ltan.wordpress.com/2016/09/02/basic-concurrency-and-parallelism-in-common-lisp-part-3-concurrency-using-bordeaux-and-sbcl-threads/ он приводит пример неправильного способа печати на верхнем уровне из потока (используя в качестве примера нити Бордо, хотя я использую Lparallel):
(defun print-message-top-level-wrong ()
(bt:make-thread
(lambda ()
(format *standard-output* "Hello from thread!")))
nil)
(print-message-top-level-wrong) -> NIL
Объяснение состоит в том, что «тот же код работал бы нормально, если бы мы не запускали его в отдельном потоке. В результате каждый поток имеет свой собственный стек, в котором переменные возвращаются.случай, даже для *standard-output*
, который является глобальной переменной, которая, как мы предполагаем, должна быть доступна всем потокам, восстанавливается внутри каждого потока! "
И это именно то, что происходит, если функция запускается в AllegroCL.Тем не менее, в SBCL функция печатает предполагаемый вывод на терминале.Означает ли это, что *standard-output*
не восстанавливается в SBCL?В общем, существует ли кроссплатформенный способ печати в *standard-output*
из потока?
В многопоточной ситуации печать на терминале обычно должна координироваться, чтобы избежать потенциальной печати из нескольких потоков одновременно,Но, похоже, нет таких функций, как atomic-format
или atomic-print
.Существует ли простой способ избежать помех печати при наличии нескольких нитей (при условии, что блокировки / взаимные блокировки слишком дороги для использования в каждой отдельной операции печати)?