如何将当前线程的绑定传递给另一个线程?

时间:2018-06-19 10:03:08

标签: concurrency common-lisp sbcl dynamic-variables

如何将所有当前线程的绑定传递给另一个线程?具体来说,我需要以下代码段将2(不是1)打印到stdout:

(defvar *foo* 1)

(let ((*foo* 2))
  (bordeaux-threads:make-thread (lambda () (print *foo*)))) ;; prints 1

当然,我可以手动复制*foo*的值,如下所示:

(let ((*foo* 2))
  (bordeaux-threads:make-thread
   (let ((foo-binding *foo*))
     (lambda () 
       (let ((*foo* foo-binding))
         (print *foo*)))))) ;; prints 2

但是有什么东西可以同时复制所有这些内容吗?

1 个答案:

答案 0 :(得分:4)

API明确关于变量共享:

  

线程和动态变量之间的交互在某些方面   案例复杂,取决于变量是否只有全局变量   绑定(由例如DEFVAR / DEFPARAMETER /顶级SETQ建立)或   已在调用线程中本地绑定(例如使用LET或LET *)。

     

1

     
    

线程之间共享全局绑定:新线程中全局变量的初始值将与父线程中的相同,     并且可以看到任何线程中对此类变量的赋值     全局绑定可见的所有线程。

  
     

2

     
    

本地绑定是引入它们的线程的本地绑定,     

除外   
     

3

     
    

MAKE-THREAD调用者中的本地绑定可能会也可能不会与它创建的新线程共享:这是     实现定义。便携式代码不应该依赖于特定的     在这种情况下的行为,也不应该分配给这些变量     首先在新主题中重新绑定它们。

  

因此,使绑定全局而非本地似乎是最简单的(不依赖于实现)路由。

@coredump还建议查看*default-special-bindings*列表,了解可能的共享方法:

  

此变量包含将特殊变量符号与其关联的alist   用于评估绑定值的表单。在此命名的特殊变量   list将在新线程开始之前在本地绑定   执行用户代码。

     

此变量可能会在调用MAKE-THREAD进行添加/更改时反弹   默认绑定。改变这个列表的效果是不确定的,但是   早期形式优先于同一符号的后续形式,所以   可以通过查看列表的头部来覆盖默认值。

     

在新线程或调用线程中评估表单?   此列表的标准内容:打印/读卡器控制等。可以借用   弗兰兹的等价物?