adr*_*mir 5 java thread-safety executorservice
我有一个关于使用单线程执行器的问题。由于它重用同一个线程,这是否意味着如果我在一次提交调用中修改了一个对象状态,我是否可以假设在随后的提交调用中对该对象状态的另一次修改是线程安全的?让我举一个玩具的例子......
public class Main {
public static void main(String[] args) throws Exception {
final A a = new Main().new A();
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return a.modifyState();
}
};
/* first call */
Future<Integer> result = executor.submit(callable);
result.get();
/* second call */
result = executor.submit(callable);
int fin = result.get();
System.out.println(fin);
executor.shutdown();
}
class A {
private int state;
public int modifyState() {
return ++state;
}
public int getState() {
return state;
}
}
}
Run Code Online (Sandbox Code Playgroud)
所以我正在共享对象 A。我提交一个可调用对象并首先修改它的状态(请参阅 /* first call / )。然后我再做一次提交调用,再次修改 A 状态。(/第二次通话*/)。现在我的大问题
可以这么说吗,因为它是同一个线程,第二次提交调用会看到 A.state 为 1?或者在某些情况下它也可以将其视为 0?
所以基本上我是问在单线程执行器的后续提交调用中修改未标记为 volatile/从同步块访问的变量是否安全?,因为它重用了相同的线程
线程重用对于执行程序究竟意味着什么?在单线程执行器的情况下,它真的是操作系统级别的同一个线程吗?
实际上它是单线程并不重要。ExecutorService的 javadoc指出:
内存一致性影响:在将 Runnable 或 Callable 任务提交给 ExecutorService 之前线程中的操作发生在该任务采取的任何操作之前,而后者又发生在通过 Future.get() 检索结果之前。
小智 2
Executors.newSingleThreadExecutor() 通过保证一次仅运行一个线程来提供线程安全性。它还为您提供了有关可见性的受让人,这意味着一个线程执行期间的任何状态更改都将对下一个线程执行可见。