同步以确保另一个线程可以看到对不可变对象的引用

2023-12-09

我刚刚在学习this了解新 JMM 中最终字段的行为(5 及以上)。这个概念很明确:在正确构造对象后,保证初始化的最终字段对所有线程的可见性。

但在本节的最后,我读到了这一点,这让我很困惑:

现在,说了所有这些,如果在一个线程构造一个不可变对象(即仅包含最终字段的对象)之后,您想要确保它被所有其他线程正确地看到,您通常仍然需要使用同步。例如,没有其他方法可以确保第二个线程可以看到对不可变对象的引用。

这是否意味着虽然各个最终字段(组成不可变对象)不存在同步(例如,此处的可见性)问题。但是,首次在线程中创建的不可变对象本身可能在其他线程中不可见(正确创建)?

如果是这样,虽然我们可以跨线程共享初始化的不可变对象,而不必担心线程不安全,但在创建时,它们需要像其他可变对象一样“特别注意”线程安全吗?


Final 字段的语义,定义于JLS 第 17.5 条,保证:

仅在对象完全初始化后才能看到对该对象的引用的线程保证能看到该对象的最终字段的正确初始化值。

换句话说,它说if一个线程sees一个完全初始化的对象,then它保证看到它的最终字段已正确初始化。

但是,不能保证该对象对给定线程可见。这是一个不同的问题。

如果您不使用某种同步来发布对象的引用,那么其他线程可能永远无法看到对该对象的引用。

考虑以下代码:

final class A {
  private final int x;
  A(int x) { this.x = x; }
  public getX() { return x; }
}

class Main {
  static volatile A a1 = null;
  static A a2 = null;
  public static void main(String[] args) {
    new Thread(new Runnable() { void run() { try {
      while (a1 == null) Thread.sleep(50);
      System.out.println(a1.getX()); } catch (Throwable t) {}
    }}).start()
    new Thread(new Runnable() { void run() { try {
      while (a2 == null) Thread.sleep(50);
      System.out.println(a2.getX()); } catch (Throwable t) {}
    }}).start()
    a1 = new A(1); a2 = new A(1);
  }
}

请注意,a1场是不稳定的。这确保最终,对该字段的写入将对稍后读取该字段的所有线程可见。场a2不是易失性的(因此,一个线程对此字段的写入可能永远不会被其他线程注意到)。

在这段代码中,我们可以确定线程 1 将完成执行(也就是说,它将看到a1 != null。但是,线程 2 可能会停止,因为它永远不会看到对该字段的写入a2,因为它不是易失性的。

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

同步以确保另一个线程可以看到对不可变对象的引用 的相关文章

随机推荐

  • 网格中不相交路径的近似算法

    我最近遇到了这个问题 我想我可以在这里分享它 因为我无法得到它 我们给定一个 5 5 的网格 编号为 1 25 以及一组 5 对点 它们是网格上路径的起点和终点 现在我们需要为这 5 对点找到 5 条对应的路径 这样两条路径就不会重叠 另请
  • 如何在 pytest 中将自定义部分添加到终端报告

    In pytest 当测试用例失败时 您会在报告中看到以下类别 失败详情 捕获的标准输出调用 捕获的 stderr 调用 捕获的调用日志 我想添加一些额外的自定义部分 我有一个并行运行的服务器 并且希望在专用部分中显示该服务器记录的信息 我
  • 不改变url,通过request.user查看

    我正在尝试编写一个视图 在其中检索当前登录用户的信息 我的视图如下所示 只要我将用户传递到 URL 中的视图 它就可以正常工作 def index request username template index html user get
  • 按出现次数对单词列表进行排序的最简单方法

    在 Java 中 按单词在列表中出现的次数对大型单词列表 10 000 20 000 进行排序的最佳 最简单方法是什么 我尝试了基本的实现 但出现内存不足运行时错误 因此我需要一种更有效的方法 你有什么建议 ArrayList
  • 在小型天蓝色实例中使用 Parallel.Foreach

    我有一个在小型实例上运行的 WebRole 该WebRole有一个将大量文件上传到BLOB存储的方法 根据 Azure 实例规范 小型实例只有1 core 那么 在上传这些 blob 时 Parallel Foreach 会比常规 Fore
  • URL 重写 - 查询字符串

    我有一个新闻 博客 网站 当选择单个帖子时 它会返回以下格式的网址 website net sitenews php q posts view postname 12 我正在寻求重写 url 使其显示为 website net sitene
  • 表单上的令牌方法、双重提交问题

    我花了几周的时间来研究我的表单的双重提交保护 直接说 存储令牌的会话方法不起作用 会话对于刷新页面或某人回顾其历史记录来说工作得很好 但是使用会话无法阻止通过多次单击按钮来进行经典的双重提交 我认为当在几毫秒内处理多次点击时 脚本无法足够快
  • Keras - 用于文本分析的自动编码器

    因此 我正在尝试创建一个自动编码器 它将接受文本评论并找到较低维度的表示 我正在使用 keras 我希望我的损失函数能够将 AE 的输出与嵌入层的输出进行比较 不幸的是 它给了我以下错误 我很确定问题出在我的损失函数上 但我似乎无法解决这个
  • 获取/设置开放图谱帖子的受众

    是否可以获取或设置开放图谱故事帖子的受众 朋友 只有我 公众 根据开发者脸书应该有一个隐私设置字段 我的应用程序确实具有发布权限 publish actions 和读取权限 public profile email user posts 当
  • Matlab 特殊矩阵

    有没有一个MATLAB函数可以生成这个矩阵 1 2 3 4 5 6 7 n 2 3 4 5 6 7 8 n 1 3 4 5 6 7 8 9 n 2 n n 1 n 2 2 n 1 它有名字吗 Thanks 是的 该矩阵确实有一个名称 它被称
  • Angular:加载所有指令后在控制器中运行函数

    我正在尝试编写一些代码 这些代码允许我在控制器中运行一个函数 但只有在整个 dom 设置并准备就绪后 包括指令链接函数运行等 我目前正在通过 rootScope 广播在 ctrl service 和指令之间进行通信 指令未拾取控制器加载时的
  • 如何为 Google Drive 上存储的文件设置图像缩略图

    使用 Google Drive API 我可以使用以下命令更新任何可写文件的属性files update method import datetime data modifiedTime datetime datetime utcnow i
  • 如何使用React + ES6 + webpack导入导出组件?

    我正在玩React and ES6 using babel and webpack 我想在不同的文件中构建多个组件 导入到单个文件中并将它们捆绑在一起webpack 假设我有一些这样的组件 我的导航栏 jsx import React fr
  • 获取 django 预订中的客人数量

    如果每个用户参加一个活动 他们都可以进行预订 但每个活动只有一定数量的开放空间 我想在活动中显示 10 个席位中还剩下 5 个 我似乎无法找到已预订且状态为 活跃 或 待定 的客人总数 这是我的事件模型 class Events model
  • 安装rubberduck后看不到插件?

    我是 ruby duck 的新手 已经安装了最新版本 2 0 11 安装管理员后 我转到 excel 并检查我的 com addins 它现在确实显示了rubberduck 我检查了我的程序数据文件夹 是的 rubberduck 包含所有文
  • 使用findText在谷歌应用程序脚本(documentApp)中使用正则表达式分割文本

    在谷歌文档 不是电子表格 中 我有一堵文字墙 看起来像 foo bar header foo bar bat paragraph and another paragraph and yet an other paragraph and so
  • Android:删除项目(ListView)

    我想从中删除一个项目ListView 但我不知道该怎么做 这是我的代码 public void FLYNOTE refresh int i SharedPreferences Pref getSharedPreferences nnote
  • FileProvider.getUriForFile 返回 null

    我正在尝试在设备的相机中拍照 当我调用处理图像捕获的方法时 应用程序由于空指针异常而崩溃 我不知道我的 FileProvider 缺少哪些信息 因为堆栈跟踪将空指针指向我的 FileProvider getUriForFile 语句 这是我
  • 有没有更好的方法来更改 php 中的 DOMElement->tagName 属性?

    我刚刚遇到了为我的 MVC 框架构建 Textbox 控件的情况 在完成整个文档之前 我对继承自 ServerTag 又继承自 DOMElement 的所有内容调用 PreRender 我发现更改 DOMElement 派生对象的 tagN
  • 同步以确保另一个线程可以看到对不可变对象的引用

    我刚刚在学习this了解新 JMM 中最终字段的行为 5 及以上 这个概念很明确 在正确构造对象后 保证初始化的最终字段对所有线程的可见性 但在本节的最后 我读到了这一点 这让我很困惑 现在 说了所有这些 如果在一个线程构造一个不可变对象