Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 从(并行)线程打印到终端(通用Lisp)_Multithreading_Printing_Common Lisp - Fatal编程技术网

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

Multithreading 从(并行)线程打印到终端(通用Lisp),multithreading,printing,common-lisp,Multithreading,Printing,Common Lisp,在Timmy Jose的一篇博客文章中,他给出了一个从线程内部打印到顶层的错误方法示例(以波尔多线程为例,尽管我使用的是Lparallel): 原因是“如果我们没有在单独的线程中运行,同样的代码也可以正常运行。发生的事情是,每个线程都有自己的堆栈,在那里变量被重新组合。在这种情况下,即使对于作为全局变量的*标准输出*,我们假设所有线程都可以使用它,它也会在每个线程中反弹!" 如果函数在Allegro CL中运行,则会发生这种情况。然而,在SBCL中,函数会在终端打印预期输出。这是否意味着SBCL

在Timmy Jose的一篇博客文章中,他给出了一个从线程内部打印到顶层的错误方法示例(以波尔多线程为例,尽管我使用的是Lparallel):

原因是“如果我们没有在单独的线程中运行,同样的代码也可以正常运行。发生的事情是,每个线程都有自己的堆栈,在那里变量被重新组合。在这种情况下,即使对于作为全局变量的
*标准输出*
,我们假设所有线程都可以使用它,它也会在每个线程中反弹!"

如果函数在Allegro CL中运行,则会发生这种情况。然而,在SBCL中,函数会在终端打印预期输出。这是否意味着SBCL中不会反弹
*标准输出*
?通常,是否有跨平台的方式从线程内部打印到
*标准输出*

在多线程情况下,通常应协调向终端的打印,以避免可能同时从多个流打印。但似乎没有任何像
原子格式
原子打印
这样的功能可用。当存在多线程时,有没有一种简单的方法避免打印干扰多个线程(假设锁/互斥锁对于每个单独的打印操作都太昂贵)

如果您实际上有一个全局绑定(全局环境中的绑定),它确实适用于所有线程;请参阅。仅动态(re-)绑定是线程本地的。实现在绑定这些流的方式/时间上有所不同;有时对用户程序实际有效的绑定是全局的,有时不是

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

也许您可以尝试使用乐观锁定,但我不知道在librarywise中做了什么(一些Lisp实现确实有可以使用的CAS操作)。这应该与使用的并行库正交


编辑:刚刚在SBCL手册中找到:具有无锁队列和邮箱。

如果我理解,我可以将全局
*标准输出*
推送到lparallel队列中,然后在任何线程中随时使用它,方法是查看队列,将其绑定到线程局部变量,该变量以线程
格式显示为流参数
语句?因此,即使两个线程同时执行
格式化
语句到顶层,其中一个线程将等待另一个线程完成。如果所有线程只读取(不写入)全局数据结构,那么读取操作(不带锁或原子操作)是真的吗是否保证安全?例如,不同线程中的两个
find
操作同时扫描同一全局列表中的相同或不同项?任何仅将标准输出公开给不同线程的独立输出的操作都将导致分散的输出。如果您能保证任何操作都不会修改数据结构(即使是在幕后,例如自我优化的数据结构),阅读它显然是安全的。你能举一个Lisp操作的例子吗,它看起来像只读的,但实际上是在幕后写的?(Ps:我不担心像
maphhash
这样的操作,如果你想写的话,你可以用它来写。)
(defun print-message-top-level-wrong ()
  (bt:make-thread
    (lambda ()
      (format *standard-output* "Hello from thread!")))
  nil)

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