Java Executor 工作线程的内存一致性
Java memory consistency for Executor's worker threads
根据 javadoc,Executor
的实现必须符合:
Memory consistency effects: Actions in a thread (A) prior to submitting a Runnable object to an Executor happen-before its execution begins, perhaps in another thread (B).
Pheraps 由于我的英语不好,我不清楚在 B 和另一个潜在线程 之间保证了哪种内存一致性关系(如果有的话) C 随后由 A 提交给同一个执行者。我希望下面的例子能澄清我的疑问。
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
class ExecutorTestClass {
int a = 1;
volatile boolean isDone = false;
MyRunnable mr1 = new MyRunnable("One");
MyRunnable mr2 = new MyRunnable("Two");
class MyRunnable implements Runnable {
private final String name;
MyRunnable(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println(name + ": " + ExecutorTestClass.this.a++);
isDone = true; // signal that addition has been performed
while (true) {
try {
Thread.sleep(5); // busy thread
} catch (InterruptedException e) {
}
}
}
}
public static void main(String[] args) {
ExecutorTestClass emc = new ExecutorTestClass();
Executor executor = Executors.newFixedThreadPool(2);
executor.execute(emc.mr1); // run the first MyRunnable
while (!emc.isDone) {
} // when stop spinning emc.a == 2 for this thread
executor.execute(emc.mr2); // is emc.a == 2 guaranteed?
}
}
线程执行emc.mr2.run()
是否保证emc.a == 2
? (在我的测试中总是如此,但是......是的,它们是测试)
如果没有,官方API中有接口保证emc.a == 2
吗?
不,不能保证,因为您在一个线程中更改了 emc.a
的值,但从另一个线程提交了 Runnable
。如果您在将值设置为 2 后从第一个 runnable 提交第二个 runnable,则 JavaDoc 的内存一致性效果将适用。
但是在您使用 volatile
变量 isDone
的示例中,即使不考虑 JavaDoc 中的说明,也可以达到目的。
由于您首先增加 emc.a
,然后将新值设置为 isDone
,然后检查 isDone
,它仍然会建立 happens before 关系,第二个 runnable 将始终看到更新值。
根据 javadoc,Executor
的实现必须符合:
Memory consistency effects: Actions in a thread (A) prior to submitting a Runnable object to an Executor happen-before its execution begins, perhaps in another thread (B).
Pheraps 由于我的英语不好,我不清楚在 B 和另一个潜在线程 之间保证了哪种内存一致性关系(如果有的话) C 随后由 A 提交给同一个执行者。我希望下面的例子能澄清我的疑问。
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
class ExecutorTestClass {
int a = 1;
volatile boolean isDone = false;
MyRunnable mr1 = new MyRunnable("One");
MyRunnable mr2 = new MyRunnable("Two");
class MyRunnable implements Runnable {
private final String name;
MyRunnable(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println(name + ": " + ExecutorTestClass.this.a++);
isDone = true; // signal that addition has been performed
while (true) {
try {
Thread.sleep(5); // busy thread
} catch (InterruptedException e) {
}
}
}
}
public static void main(String[] args) {
ExecutorTestClass emc = new ExecutorTestClass();
Executor executor = Executors.newFixedThreadPool(2);
executor.execute(emc.mr1); // run the first MyRunnable
while (!emc.isDone) {
} // when stop spinning emc.a == 2 for this thread
executor.execute(emc.mr2); // is emc.a == 2 guaranteed?
}
}
线程执行emc.mr2.run()
是否保证emc.a == 2
? (在我的测试中总是如此,但是......是的,它们是测试)
如果没有,官方API中有接口保证emc.a == 2
吗?
不,不能保证,因为您在一个线程中更改了 emc.a
的值,但从另一个线程提交了 Runnable
。如果您在将值设置为 2 后从第一个 runnable 提交第二个 runnable,则 JavaDoc 的内存一致性效果将适用。
但是在您使用 volatile
变量 isDone
的示例中,即使不考虑 JavaDoc 中的说明,也可以达到目的。
由于您首先增加 emc.a
,然后将新值设置为 isDone
,然后检查 isDone
,它仍然会建立 happens before 关系,第二个 runnable 将始终看到更新值。