Is the SBCL threading behaviour described in  right? (refs at end)
Two "motivating examples":
Example 1. for SLIME users:
at the SLIME REPL, type:
(sb-thread:make-thread #'(lambda () (format t "hello, world~%") (force-output)))
Isn't it reasonable to expect similar behaviour to a plain
(format t "hello, world~%") here (the output actually goes to
the inferior-lisp buffer)?
Example 2. using LTK:
In Lisp TK  , the function
with-ltk sets up a dynamic environment for the running of tk
functions; for example:
(with-ltk () (pack (make-instance 'button :text "Press Me")))
This creates a new tk window, creates and packs a button widget
inside it, and starts an event loop.
Suppose I wish to execute some tk commands in a separate thread, e.g.
(pack (make-instance 'button :text "Press Me"))
(pack (make-instance 'button :text "Delayed")))))
This does not work.
It's easy enough to get the SLIME example to work correctly:
(let ((f *standard-output*))
(let ((*standard-output* f))
(format t "hello, world~%")
The problem is that SLIME has bound a new value onto *standard-output*,
but the new thread does not inherit it. Luckily we know the dynamic
variable used by FORMAT, so can explicitly pass the value across
via a lexical binding.
This isn't so easy to do in the LTK example. What special variables
do the tk functions use? They're not necessarily exported from
the ltk package. A quick grep through the source reveals 21 special
variables - if we get the thread in the example to inherit all of these,
then it works (thread safety of the underlying library aside).
But this seriously breaks modularity. If the maintainer of the package
binds a new dynamic variable, then our program breaks.
Surely this can't be right?
It's not as if others have not already encountered the problem. In each
case, an ad hoc solution is produced. In  a special function call
is used (what if that function had not existed?). In  (which seems to
have set the precedent for this behaviour), dynamic variable inheritance
is also explicit, but this suffers from exactly the same problems as outlined
It seems to me that there are a number of (potentially conflicting) requirements
for the behaviour of dynamic variables with respect to threads.
1) the minimum memory taken by a new thread should not be proportional to the
number of dynamic variables 
2) dynamic bindings in different threads should not conflict.
3) it should not be necessary to know all of a package's dynamic variables
in order to be able to spawn a new thread using one of that package's functions.
4) code should be able to communicate by changing the value of a dynamic variable.
The current situation breaks 3), and it also breaks 4) apart from
the special case of globally defined (and never bound) variables.
You could try to get around 3) by having all packages export a
list of variables that need to be inherited, but this seems error prone,
and one would end up conflicting 1) anyway.
Why are global variables special anyway?
(defparameter *x* 99)
(make-thread #'(lambda () (print *x*)))
behave differently depending on whether the thread executing
the code has, or has not, bound *x*?
A possible solution: how about changing the semantics so all slots (rather
than values) for dynamic variables are inherited? A little bit more like
dynamic closures than I understand the previous SBCL implementation to
So the above example would always print 99, regardless of
previous bindings. Moreover, the child thread would be
able to (setf *x*) and have the value seen by the parent too.
If this could be done without a horrendous performance hit,
(and having had a look at the current implemention, I think
it probably can) it would solve all the problems raised above.
There remain the points raised in :
> 1) dynamic-extent
> Suppose your package has a non-exported special, binds it, promises it's
> going to be dynamic extent and proceeds to call user code. The user
> code spawns a thread and the promise is broken.
Surely declaring a special to be dynamic extent is fraught with peril
anyway, as someone might just use the value and break your
> 2) gc
> It's hard to control giving out references to objects. Yeah, it's
> similar to 1), but colour of the smoke is different.
If the value isn't copied, merely a reference to the value,
then you still have control over the reference (unless someone
explicitly copies the value, which could happen anyway).
> 3) scaling
> When starting up, a thread is given a snapshot of the parent thread's
> current values for dynamic variables. This means that the minimum
> memory required by a thread is proportional to the number of specials.
It's possible to get around this by trading off per-thread space for
dynamic LET time. Rather than have thread-local storage point directly to
values of locally bound dynamic variables, as currently, it could point to
a (potentially shared) set of dynamic variable slots (pointers to values),
an "environment". The first time a dynamic LET occurs in a thread, the
environment would be copied (copy on write); subsequent dynamic LETs would
modify the same environment. Note that the environment would contain
no values, just pointers to values, so no locking would be necessary.
So if you had many threads, none of which did any dynamic LETs, they
would all share the same environment.
As far as performance goes, it might be a little slower, but it might
make up for that with unconditional code (no need to check against
Sorry about the long post and my likely non-standard terminology;
(I'm quite new to Common Lisp). I hope that someone out there
might understand where I'm coming from!