so why does each thread use the value of i as whatever value it happens to have when the thread is scheduled, instead of the presumably pass-by-value value it's given?
It's pass-by-value as far as the loop body goes, however that does not apply to the threads created in it. The threads will still refer to i
by its address.
To fix this problem, you need to create a closure inside the loop:
import std.stdio, core.thread;
void main() {
ThreadGroup tg = new ThreadGroup();
foreach (int i; 1 .. 5)
(i =>
tg.create( () => writeln(i) )
)(i);
tg.joinAll();
}
The lambda parameter will be stored in the closure, giving each thread its own copy.