为什么同步字段变量并在同步块内递增它会导致打印乱序?

2023-12-09

我有一个简单的代码片段

public class ItemManager {

    private Integer itemCount = 0;

    public void incrementAndPrint() {
        synchronized(this) { 
            System.out.println(++itemCount + " ");
        }
    }

    public static void main(String[] args) {
        ItemManager manager = new ItemManager();
        ExecutorService executor = Executors.newFixedThreadPool(20);

        for (int i = 0; i < 10; i++) {
            executor.submit(manager::incrementAndPrint); 
        }
        executor.shutdown();
    }
}

按预期产生 1 2 3 4 5 6 7 8 9 10 。我还可以使用对象实例创建另一个字段并锁定它

    private Integer itemCount = 0;
    private Object lock = new Object();

    public void incrementAndPrint() {
        synchronized(lock) {
            System.out.println(++itemCount + " ");
        }
    }

它还会按预期产生 1 2 3 4 5 6 7 8 9 10 。

但是,如果我尝试锁定要递增和打印的同一个对象

    private Integer itemCount = 0;

    public void incrementAndPrint() {
        synchronized(itemCount) {
            System.out.println(++itemCount + " ");
        }
    }

该操作将保持原子性,但结果是无序的:2 1 3 4 5 6 7 8 9 10。

我知道synchronized(this)或者同步整个方法将解决我所有的问题。我只是不明白为什么我可以锁定一个字段(Object lock),但无法锁定另一个 (Integer itemCount)?里面的所有东西不应该是synchronized块是否可以正确锁定,无论该对象是什么,只要它是在所有线程之间共享的单个对象?


IntegerJava 中的 s 是不可变的。你打电话时++itemCount,您实际上正在执行三个操作:首先,Integer被拆箱到int与价值Integer。那么,这个原始的int递增,最后递增的int被自动装箱回Integer。所以事实上,你最终拥有不同的 Integer实例。由于您在不同的实例上进行同步,因此同步没有意义,并且您会看到无序打印。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么同步字段变量并在同步块内递增它会导致打印乱序? 的相关文章

  • iText7:如何获取段落的实际宽度

    在添加到文档之前 我需要知道段落的宽度 以磅为单位 我在这里搜索并找到了 Alexey 关于段落高度的答案 所以我用宽度做了它 但它不起作用 无论段落有多长 始终返回矩形的宽度 我尝试了这段代码 private float getRealP
  • 如何将 Excel 中的图表导出为图形

    我有一系列 Excel 电子表格 每个电子表格至少包含一页数据和一页根据数据创建的图表 我需要捕获 不从数据中重新生成 将现有图表作为网络友好图像 这可以通过 Java 或 Net 实现吗 我知道 POI 的东西 Java 不会这样做 或者
  • 等待 .NET 线程启动的正确方法是什么?

    我在微软网站上的线程教程中阅读了以下内容 http msdn microsoft com en us library aa645740 v vs 71 aspx http msdn microsoft com en us library a
  • 如何找出已使用的 JAR?

    在更大的项目中 我们可能会使用大量的 JAR 如何找出项目 而不是整个项目 中的某个模块 包正在使用哪些 JAR 有什么工具 技术等吗 较大的项目通常使用类似的构建工具maven http maven apache org or ant h
  • JUnit 测试方法无法返回值

    为什么 JUnit 测试方法无法返回值 文档 https junit org junit5 docs current user guide writing tests classes and methods说 强调我的 测试方法和生命周期方
  • 我如何通过代码在 Anylogic 中创建路径空间标记元素

    我在anyloigic方面完全是菜鸟 现在我正在尝试通过代码创建简单的网络 具有两个点节点的网络 以及链接这些节点的路径 遇到一些问题 当我运行模型时 控制台显示 使用初始化 方法 但我已经知道 初始化方法在较低版本中已被弃用 我使用的是8
  • 如何将 openapi-generator 中的客户端包含在 gradle java 应用程序中?

    我想创建一个 gradle java 应用程序 它从 openAPI 规范文件生成客户端并使用该客户端 所以我创建了一个java应用程序gradle init 类型 应用程序 语言 Java DSL groovy 测试框架 Junit Ju
  • 正则表达式或用单个空格替换多个空格的方法

    你能告诉我有没有办法在java或spring中用单个空格替换多个空格 有相同的 stringUtils 函数吗 like 1 test test test test 2 test test test test 3 test test tes
  • Java SWT 用户输入验证

    在 SWT 中进行用户输入验证时 Java 约定是什么 我读到有 FieldEditors 它们是非常方便的字段 但遗憾的是仅适用于首选项和对话框 我还了解到有一个 IValidator 接口 但它经常与数据绑定一起使用 就我而言 我的大多
  • 如何调试内部错误?

    所以我有课Foo最终应该调整并重新加载类 它也有一个方法 private void redefineClass String classname byte bytecode ClassFileLocator cfl ClassFileLoc
  • Spring Data (JPA) 多个存储库,没有很多类

    在我当前的项目中 我使用 Spring Data JPA 并且有 20 多个 Entity类 我想为它们创建存储库 但创建另一个类 每个类适用于任何模型 Repository注释似乎是某种矫枉过正和大量 重复 代码 所有存储库类将如下所示
  • 何时使用 clone() 以及 addAll() 和 add() 的实际工作原理

    我正在使用 Java 和 MySQL 我的项目中有大约 60 个交易屏幕 我曾经用过add and addAll 复制的功能ArrayList 例如 List
  • Java ZIP - 如何解压缩文件夹?

    是否有任何示例代码 如何将 ZIP 中的文件夹部分解压到我想要的目录中 我已将文件夹 FOLDER 中的所有文件读取到字节数组中 如何从其文件结构创建 我不确定你所说的部分是什么意思 您的意思是在没有 API 帮助的情况下自己完成吗 如果您
  • Android 改造参数化@Headers

    我正在使用 OAuth 每次发出请求时都需要将 OAuth 令牌放入标头中 我看到 Header注释 但是有没有办法让它参数化 以便我可以在运行时传入 这是概念 Header Authorization OAuth var api vers
  • 为什么我们在同一台服务器上使用多个应用程序服务器实例

    我想这是有充分理由的 但我不明白为什么有时我们会在同一物理服务器上放置例如 5 个具有相同 Web 应用程序的实例 这与多处理器架构的优化有关吗 JVM 或其他允许的最大内存限制 嗯 过了很长一段时间我又看到这个问题了 一台机器上的多个 J
  • Java并发锁和条件的使用

    我可以用object wait object notify and synchronized blocks解决生产者消费者类型的问题 同时我可以使用locks and conditions from java util concurrent
  • 使用从 java 程序调用的 Windows 命令提示符将具有多个连续空格的字符串作为参数传递给 jar 文件

    我想使用在另一个java程序中调用的Windows命令提示符将带有多个连续空格的字符串作为参数传递给jar文件 java 文件是这样的 它打印它的所有参数 package src public class myClass public st
  • 使用基于Optional内容的流

    我从不受我控制的服务获取可能为空的地图 并且想要处理它 比方说 过滤 映射并减少到我需要的单个元素 问题 是否有从Optional到Stream的 链接 我尝试过 除其他外 return Optional ofNullable getMap
  • 如何在 Android 上设置 Google Drive API?

    我一直在尝试将 Google Drive 功能集成到我的应用程序中 但我无法使用任何内置功能 因此我相信我要么错过了一个步骤 要么做得不正确 我正在遵循官方的 Google 开发者指南 https developers google com
  • JAAS keytab 配置的相对路径

    我有一个系统 其中 NET 客户端使用 Kerberos 针对 Java 服务器进行身份验证 一切正常 但我正在尝试改进服务器配置 目前一个keytab根目录中需要文件C 因为我的jaas配置文件看起来像这样 Server com sun

随机推荐