在https://stackoverflow.com/posts/comments/97440894?noredirect=1的另一篇文章中提到了对Lisp对象的多线程访问的主题,但作为一个侧面问题,我希望进一步澄清。
通常,Lisp函数(以及特殊形式,宏等)似乎自然地分为对象的访问器和修饰符。共享对象的修饰符在多线程应用程序中显然是有问题的,因为同时发生的更新可能相互干扰(需要保护锁,原子操作等)。
但潜在的接入干扰问题似乎不太清楚。当然,任何访问器都可以编写为包含潜在修改代码,但我想认为基本的Lisp访问器操作(在CLHS中指定并针对各种平台实现)不会。但是,我怀疑出于效率的原因,可能会出现极少数例外 - 如果在没有保护的情况下在多线程代码中使用,则很有必要注意这些异常。 (我所说的那种例外不是像maphash
这样的操作,可以用作存取器和修改器。)
如果具有实施经验的任何人都可以指向至少一个内置的仅访问操作(例如在SBCL或其他来源中),其中包括可能有麻烦的修改,那将会很有帮助。我知道保证很难得到,但启发式指导也很有用。
任何执行此操作的代码都是支持多线程的实现中的错误。 SBCL保护着名的*world-lock*
不具有线程安全功能。
如果您有真正需要不可变结构的理由,请使用带有只读defstruct的defconstant
。 (defstruct number (value :read-only t))
(defconstant +five+ (make-number 5))