同步和可见范围

2023-11-29

我一直在阅读 Java 并发性,但忘记了这样一个事实:使用同一锁的两个线程中的同步块也会影响变量的可见性,即使它们没有定义为“易失性”。如果我有这样的代码

Object lock = new Object();
boolean a = false, b = false, c = false;

void threadOne() {

   a = true;
   synchronized(lock) {
      b = true;
   }
   c = true;

}

void threadTwo() {

   while (true) {
      synchronized(lock) {
         if (a && b && c) break;
      }
   } 

}

...并且 threadOne 和 threadTwo 将由不同的线程调用:

  1. 是否保证代码会跳出 while 循环?

  2. 如果我们从方程中删除变量 c 会怎么样?我想知道是否只有 b 保证在 threadTwo 中可见,因为它位于同步块内。


是否保证代码会跳出 while 循环?

不。Java 内存模型是根据“发生在之前” 关系:

两个操作可以按先行发生关系排序。如果一个操作发生在另一个操作之前,则第一个操作对第二个操作可见并且排序在第二个操作之前。

该规范继续说道:

如果动作 x 与后续动作 y 同步,那么我们也有 hb(x, y)。

where hb代表发生在之前,并且

监视器 m 上的解锁操作与 m 上的所有后续锁定操作同步(其中“后续”根据同步顺序定义)。

另请注意:

如果 hb(x, y) 和 hb(y, z),则 hb(x, z)。

所以在你的例子中,synchronized(lock) around b将为接下来的读取建立一个发生在之前的关系,因此值b保证在也使用的其他线程中可见synchronized(lock)。明确地说,

hb(write to b in threadOne, unlock in threadOne) AND 
hb(unlock in threadOne, lock in threadTwo) AND 
hb(lock in threadTwo, read from a in threadTwo) IMPLIES 
hb(write to b in threadOne, read from b in threadTwo) 

相似地,a将保证对其他线程可见。明确地说,

hb(write to a in threadOne, lock in threadOne) AND 
hb(lock in threadOne, unlock in threadOne) AND 
hb(unlock in threadOne, lock in threadTwo) AND 
hb(lock in threadTwo, read a in threadTwo) IMPLIES 
hb(write to a in threadOne, read a in threadTwo). 

写入然后随后读取c没有发生在关系之前,因此,根据规范,写入c不一定可见threadTwo.

如果我们从方程中删除变量 c 会怎么样?我想知道是否只有 b 保证在 threadTwo 中可见,因为它位于同步块内。

是的,见上文。

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

同步和可见范围 的相关文章

随机推荐

  • < 在 Markdown 中有特殊含义?

    tmp md Choices for blank 91 A pa gt pb B pa
  • 使用模式重命名文件

    我的文件名看起来像 er log 0 0 1 20150807 194034 8 jar 它遵循的格式类似于 artifactId version timestamp jar 我想将其重命名为artifactId jar I tried g
  • Java 泛型:语法解释

    我是 java 泛型新手 我的问题是 public static lt E gt void printArray E inputArray 在上面的语句中 当函数的返回类型为 void 时 为什么我们使用E before void 为什么这
  • 如何计算group by语句中总数的百分比?

    我有一张表 其中每个销售人员每天每笔销售有 1 条记录 NAME DATE joe 1 1 13 joe 1 1 13 joe 1 1 13 dave 1 1 13 joe 1 2 13 我用它来创建和填充表 create table sa
  • PHP CURL 重定向

    我对 php 很陌生 目前我面临有关 php curl post 和重定向的问题 我已经编写了大量代码来连接跨域 api 在此 API 中 响应会将我的页面重定向到另一个页面 所以 现在我面临的是我也无法遵循 api 响应 这意味着在我的
  • 将 NSString 转换为 ASCII 二进制等效值(然后再次转换回 NSString)

    我在这方面遇到了一些问题 我想获取一个 NSString 并将其转换为仅包含 0 1 个值的整数数组 该数组表示与 ascii 字符串等效的二进制值 例如说我有以下内容 NSString string A Decimal value 65
  • Kubernetes API 服务器,提供 pod 日志

    REST API 请求 GET POST PUT对 Kubernetes API 服务器的请求 响应等都是简单易懂的 比如kubectl create
  • 在mvc项目中使用Jquery删除表中的行

    我生成以下内容html code table for int i 0 i lt Model listUsers Count i tr td Html DisplayFor m gt m listUsers i Name td td Html
  • 折线图的“输入”选择可以设置动画吗?

    我有一个更新得非常好的折线图 直到新数据进入问题 此时 更新 选择会按应有的方式向下动画 但新数据不会 很难解释发生了什么 但一张 gif 胜过一千个单词 注意它何时转换 down 我已将图形包装在具有更新和渲染方法的类中 这是我写的渲染方
  • 如何在 IIS7 中托管 WCF 数据服务 (OData)?

    有谁知道如何在 IIS7 中托管 WCF 数据服务 或 OData 我看到很多有关托管 WCF 的文章 但没有一篇专门针对 WCF 数据服务 非常感谢 主持一个WCF数据服务在 IIS 中实际上是默认选项 这是一个非常简单的 3 步过程 创
  • SPNEGO:成功协商和身份验证后的后续调用

    在过去的几天里 我使用以下方法构建了一个概念验证演示GSS API and SPNEGO 目的是让用户通过 Http RESTful Web 服务单点登录访问我们的自定义应用程序服务器提供的服务 持有有效 Kerberos 票证授予票证 T
  • 在 git clone 命令中使用密码克隆 BitBucket 存储库会导致问题

    我正在尝试使用我的密码git clone命令克隆存储库 但总是会出现以下错误 remote Login failed due to incorrect login credentials or method remote If you ar
  • 我的 Android 应用程序可以在隐身选项卡中打开 URL 吗?

    我们都知道如何在 Android 的浏览器中打开 URL 做这样的事情 Intent browserIntent new Intent android intent action VIEW Uri parse url context sta
  • 在mysql中创建触发器时出现错误“1064”?

    在 mysql 中创建触发器时 我收到错误 1046 我的查询是 CREATE TABLE test Employee id int first name VARCHAR 30 last name VARCHAR 15 start date
  • extjs:加载时如何设置组合框的值

    我正在寻找一个load侦听器 当组合框启动时 load将被调用并向服务器执行 ajax 以获得组合框的正确显示值 但是 加载函数永远不会被调用 我该如何修复它 我想在组合框之前显示文本 所以我添加了属性fieldLabel Save log
  • 量角器未知错误,从 DOM 中删除属性

    我是量角器新手 试图从 DOM 中删除属性 但收到 未知错误 我不确定可能是什么问题 我有一个带有自定义指令的简单 HTML 我正在尝试删除它以使我的测试用例通过
  • 在 Google Colaboratory 上使用 GPU 运行 LightGBM/ LGBM

    我经常在 Google Colabatory 上运行 LGBM 我刚刚发现这个页面说 LGBM 默认设置为 CPU 所以你需要先设置 https medium com am sharma lgbm on colab with gpu c1c
  • Clearcase 7.1.2,VOB 分割

    我们当前设置了 VOB 源代码和文档驻留在同一个 VOB 中 为了减少 VOB 下载时间 我们现在希望将文档移动到新的 VOB 以便只有代码部分保留在旧的 VOB 中 由于有很多文件夹和文件 因此不可能手动重新定位每个文件 文件夹 为此 我
  • 使用框在同一文件上绘制不同的列

    我有一个看起来像这样的文件 cat myfile dat 1 8 32 19230 1 186 3 985 1 8 64 9620 0 600 7 877 1 8 128 4810 0 312 15 136 1 8 256 2410 0 2
  • 同步和可见范围

    我一直在阅读 Java 并发性 但忘记了这样一个事实 使用同一锁的两个线程中的同步块也会影响变量的可见性 即使它们没有定义为 易失性 如果我有这样的代码 Object lock new Object boolean a false b fa