我不明白'a'的值为0,为什么'a'不是10,那段代码的运行过程是怎样的,是否需要从Java内存模型来分析?这是我的测试代码
package com.study.concurrent.demo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
//@SpringBootTest
@Slf4j
class DemoApplicationTests {
int a = 0;
int b = 0;
@Test
void contextLoads() {
ExecutorService executorService = Executors.newFixedThreadPool(1);
// final Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < 10; i++) {
executorService.execute(() -> {
// try {
// semaphore.acquire();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
add();
bdd();
// log.info("a: {},concurrent_id: {}",a,Thread.currentThread().getName());
// semaphore.release();
});
}
executorService.shutdown();
log.info("The final value of a:{}",a);
log.info("The final value of b:{}",b);
}
public void add(){
a++;
}
public void bdd(){
b++;
}
}
两个原因:
-
您不是在等待线程完成,您只是关闭线程池(即:导致线程池拒绝新任务但继续处理现有任务)。
-
您没有在线程池中的写入和主线程中的读取之间建立发生之前的关系。
您可以通过(以及其他方法)执行此操作:
- 读取前获取信号量
a
;
- 通过使用
submit
代替execute
得到一个Future<?>
对于提交的每个任务,并调用Future.get()
所有返回的 future 的方法。它记录在的 JavadocExecutorService https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html这建立了一个发生之前。
第一点是“主要原因”a
结果为零:如果我在本地运行它,并等待线程池终止,a
结果是 10。
然而,仅仅因为它的结果是 10,并不意味着如果不注意第二点,代码就能正常工作:您需要应用 Java 内存模型来保证正确运行。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)