【问题标题】:How to convey current thread's bindings to another thread?如何将当前线程的绑定传递给另一个线程?
【发布时间】:2018-06-19 10:03:07
【问题描述】:

如何将当前线程的所有绑定传递给另一个线程?具体来说,我需要以下 sn-p 将2(不是1)打印到标准输出:

(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

但是有什么东西可以一次复制所有这些吗?

【问题讨论】:

    标签: concurrency common-lisp sbcl dynamic-variables


    【解决方案1】:

    API 明确表示变量共享:

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

    1.

    全局绑定在线程之间共享:新线程中全局变量的初始值将与父线程中的相同, 并且在任何线程中对这样一个变量的赋值都是可见的 全局绑定可见的所有线程。

    2.

    本地绑定对于引入它们的线程是本地的, 除了那个

    3.

    MAKE-THREAD 调用者中的本地绑定可能会也可能不会与它创建的新线程共享:这是 实现定义。可移植代码不应依赖于特定的 在这种情况下的行为,也不应该在没有 首先在新线程中重新绑定它们。

    所以使绑定全局而不是本地似乎是最简单(不依赖于实现)的路线。

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

    此变量保存一个将特殊变量符号与 用于评估绑定值的表单。在此命名的特殊变量 list 将在新线程开始之前在本地绑定 执行用户代码。

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

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

    【讨论】:

    • 另见关于*default-special-bindings*的说明
    • *Default-special-bindings* 是直接的方法。退回到全局的、有效的非特殊行为似乎不可取。
    • 如果你想在主线程中改变一个变量,你确定会更容易吗?
    • 我通常确信根本不更改全局变量会更容易(与动态重新绑定相反)。如果您需要线程(或进程,或其他)之间的通信,请使用通道/邮箱/套接字/队列/其他。
    • 我的意思不是从系统设计的角度来看,我的意思是一个快速而肮脏的小应用程序“只适合我”。但我明白你的意思,我会在稍后添加警告。
    猜你喜欢
    • 2011-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多