java - 为什么我的线程在访问同步方法时会给我这个输出?
问题描述
我正在尝试多线程和同步,所以我创建了这个在所有线程之间共享的简单对象:
public class SharedObject {
private int count = 0;
public synchronized int getCount(){
return count;
}
public synchronized void incrementCount(){
count++;
}
}
它由 3 个线程以这种方式访问:
public static void main(String[] args) throws Exception {
SharedObject sharedObject = new SharedObject();
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);
Runnable task = () -> {
for(int i = 0; i < 10; i++){
System.out.println("Thread : " + Thread.currentThread().getName()
+ " count : " + sharedObject.getCount());
sharedObject.incrementCount();
try{
Thread.currentThread().sleep(2000);
}
catch (Exception e){}
}
};
executor.submit(task);
executor.submit(task);
executor.submit(task);
executor.shutdown();
executor.awaitTermination(1, TimeUnit.HOURS);
System.out.println("Final : " + sharedObject.getCount());
}
我的输出如下:
Thread : pool-1-thread-2 count : 0
Thread : pool-1-thread-1 count : 0
Thread : pool-1-thread-3 count : 0
Thread : pool-1-thread-3 count : 3
Thread : pool-1-thread-2 count : 3
Thread : pool-1-thread-1 count : 3
Thread : pool-1-thread-2 count : 6
Thread : pool-1-thread-1 count : 6
Thread : pool-1-thread-3 count : 6
...
如果我的理解是正确的(如果我错了,请纠正我),这是因为:
第一个线程调用
getCount()
,获取方法上的锁,一旦他打印计数值,释放锁,然后由第二个线程获取,然后调用getCount()
最后一个线程当所有 3 个线程都完成调用
getCount()
时,它们中的每一个都在调用,incrementCount()
并且由于方法是同步的,每个线程在增加计数之前都会看到更新的值,这解释了为什么我们在输出中看到 +3 的跳转线程一结束,它就调用
sleep(2000)
自己,但由于调用速度如此之快,似乎三个线程同时开始和停止休眠
但是,当我删除时sleep(2000)
,我得到以下输出:
Thread : pool-1-thread-3 count : 0
Thread : pool-1-thread-2 count : 0
Thread : pool-1-thread-1 count : 0
Thread : pool-1-thread-2 count : 2
Thread : pool-1-thread-3 count : 1
Thread : pool-1-thread-2 count : 4
Thread : pool-1-thread-1 count : 3
Thread : pool-1-thread-2 count : 6
Thread : pool-1-thread-3 count : 5
Thread : pool-1-thread-2 count : 8
Thread : pool-1-thread-1 count : 7
Thread : pool-1-thread-2 count : 10
Thread : pool-1-thread-3 count : 9
Thread : pool-1-thread-2 count : 12
Thread : pool-1-thread-1 count : 11
Thread : pool-1-thread-2 count : 14
我不明白这怎么会发生。例如,如果在他之前看到计数等于2并增加它,怎么能thread-3
看到计数等于1 ?thread-2
任何解释将不胜感激,以帮助我更好地理解多线程同步环境中的 Java。感谢您的时间。
解决方案
仅仅因为一个线程在另一个之前读取一个值并不意味着它会在另一个之前打印它。Yo 需要在同步块内以原子方式完成读取和打印,以获得该保证。
所以你可以拥有的是
线程 3 读取并打印值 (0): 线程:pool-1-thread-3 计数:0
线程 2 读取并打印值 (0):线程:pool-1-thread-2 计数:0
线程 1 读取并打印值 (0):线程:pool-1-thread-1 计数:0
线程 3 递增值 (1)
- 线程 3 读取值 (1)
- 线程 2 递增值 (2)
- 线程 2 读取并打印值 (2): 线程:pool-1-thread-2 计数:2
- 线程 3 打印它之前读取的值: 线程 : pool-1-thread-3 count : 1
推荐阅读
- c++ - 如何在 tinyxml2 中附加两个 xml 文件
- javascript - NodeJS:无法通过带有 start-server-and-test 的包脚本设置 PERCY_TOKEN
- python - 无法关闭 Django 消息警报
- sql - 如何选择在某列中具有多个相同值的所有不同行
- angular - 过滤导航开始和结束的角度路由器事件
- excel - 运行时错误9。下标超出范围错误
- algorithm - 给定一组边和一个无向图,我如何选择最好的边添加到图中以最小化最短路径?
- pandas - 从数据框中返回单个值作为数字
- java - 有没有办法使用spring boot rest控制器返回HTML页面作为响应?
- c++ - 如何对特征张量执行某些操作?