产生问题的示例代码:
import std.stdio, core.thread;
void main() {
ThreadGroup tg = new ThreadGroup();
foreach (int i; 1 .. 5)
tg.create( () => writeln(i) );
tg.joinAll();
}
示例输出:
3
5
5
5
5
(预期输出为整数1到5。)
我不明白为什么会发生这种情况 - i
不是引用类型,也没有引用它在委托中使用,所以为什么每个线程都使用{{1}的值作为调度线程时发生的任何值,而不是它给出的大概传值值?
我做了一些像这样的蹩脚尝试,但没有成功:
i
我很好奇为什么这不起作用。是不是每次都宣布一个新的foreach (int i; 1 .. 5) {
scope j = i;
tg.create( () => writeln(j) );
}
?为什么每个线程都引用相同的j
(线程调度时其值通常为5)?
答案 0 :(得分:6)
那么为什么每个线程都使用i的值作为调度线程时发生的任何值,而不是它给出的值传递值?
就循环体而言,它是值传递,但这不适用于在其中创建的线程。线程仍将通过其地址引用i
。
要解决此问题,您需要在循环内创建一个闭包:
import std.stdio, core.thread;
void main() {
ThreadGroup tg = new ThreadGroup();
foreach (int i; 1 .. 5)
(i =>
tg.create( () => writeln(i) )
)(i);
tg.joinAll();
}
lambda参数将存储在闭包中,为每个线程提供自己的副本。