从(并行)线程(通用Lisp)打印到终端

时间:2019-03-25 15:17:03

标签: multithreading printing common-lisp

https://z0ltan.wordpress.com/2016/09/02/basic-concurrency-and-parallelism-in-common-lisp-part-3-concurrency-using-bordeaux-and-sbcl-threads/的Timmy Jose的博客文章中,他给出了一个错误的示例,该错误的方法从线程内部打印到顶层(以Bordeaux Threads为例,尽管我使用的是Lparallel): / p>

(defun print-message-top-level-wrong ()
  (bt:make-thread
    (lambda ()
      (format *standard-output* "Hello from thread!")))
  nil)

(print-message-top-level-wrong) -> NIL

解释是:“如果我们没有在单独的线程中运行相同的代码,它将运行良好。发生的情况是每个线程都有其自己的堆栈,变量会反弹。在这种情况下,即使对于{{ 1}},这是一个全局变量,我们认为应该对所有线程可用,它在每个线程内反弹!”

如果该函数在Allegro CL中运行,这正是发生的情况。但是,在SBCL中,该功能确实会在终端上打印预期的输出。这是否意味着*standard-output*在SBCL中没有反弹?通常,是否有跨平台的方法可以从线程内部打印到*standard-output*

在多线程情况下,通常应协调到终端的打印,以避免可能同时从多个流中进行打印。但是似乎没有可用的功能*standard-output*atomic-format。当有多个线程时,是否有一种简单的方法来避免打印干扰(假设锁/互斥锁对于每个单独的打印操作来说都太昂贵了?)?

1 个答案:

答案 0 :(得分:2)

如果实际上有一个 global 绑定(在全局环境中是一个绑定),它确实适用于所有线程;请参阅documentation for bt:make-thread。只有动态(重新)绑定是线程本地的。不同的实现方式/绑定它们的方式。有时实际上对用户程序有效的绑定是全局的,有时不是全局的。

我喜欢在需要时使用某种队列或通道来协调输出;我还没有遇到过锁定开销过高的情况。

也许您可以尝试使用乐观锁定进行操作,但是我不知道针对库进行了哪些操作(某些Lisp实现确实具有可以使用的CAS操作)。这应该与所使用的并行性库正交。

EDIT :只能在SBCL手册中找到:sb-concurrency具有无锁队列和邮箱。