gpt4 book ai didi

java - Java并发中 "program order rule"的解读

转载 作者:搜寻专家 更新时间:2023-10-30 19:52:01 24 4
gpt4 key购买 nike

程序顺序规则规定“线程中的每个操作都发生在该线程中程序顺序中稍后出现的每个操作之前”

1.我读了另一个thread那个 行动

  • 读取和写入变量
  • 监视器的锁定和解锁
  • 用线程开始和连接

  • 这是否意味着读取和写入可以按顺序更改,但读取和写入不能通过第 2 行或第 3 行中指定的操作更改顺序?

    2.“节目顺序”是什么意思?

    用例子解释会非常有帮助。

    其他相关问题

    假设我有以下代码:
    long tick = System.nanoTime(); //Line1: Note the time
    //Block1: some code whose time I wish to measure goes here
    long tock = System.nanoTime(); //Line2: Note the time

    首先,它是一个单线程应用程序,以保持简单。编译器注意到它需要检查两次时间,并且还注意到一个与周围的时间注释行没有依赖关系的代码块,因此它看到了重新组织代码的潜力,这可能导致 Block1 没有被计时调用包围在实际执行期间(例如,考虑这个订单 Line1->Line2->Block1)。但是,我作为程序员可以看到 Line1,2 和 Block1 之间的依赖关系。 Line1 应该紧跟在 Block1 之前,Block1 需要有限的时间来完成,然后 Line2 紧随其后。

    所以我的问题是:我是否正确测量了块?
  • 如果是,是什么阻止编译器重新排列顺序。
  • 如果不是,(经过恩诺的回答后认为是正确的)我可以做些什么来防止它。

  • P.S.:我从 another question 偷了这个代码我最近问过。

    最佳答案

    这可能有助于解释为什么首先存在这样的规则。

    Java 是一种过程语言。 IE。你告诉 Java 如何为你做一些事情。如果 Java 没有按照您编写的顺序执行您的指令,那么它显然是行不通的。例如。在下面的例子中,如果 Java 会做 2 -> 1 -> 3 那么炖菜就会被毁掉。

    1. Take lid off
    2. Pour salt in
    3. Cook for 3 hours

    那么,为什么规则不简单地说“Java 按照您编写的顺序执行您编写的内容”?简而言之,因为Java很聪明。以下面的例子为例:
    1. Take eggs out of the freezer
    2. Take lid off
    3. Take milk out of the freezer
    4. Pour egg and milk in
    5. Cook for 3 hours

    如果 Java 像我一样,它只会按顺序执行它。然而,Java 足够聪明,可以理解它的效率更高,并且如果它执行 1 -> 3 -> 2 -> 4 -> 5(您不必再次走到冰箱,并且这不会改变食谱)。

    因此,“线程中的每个操作都发生在该线程中按程序顺序稍后出现的每个操作之前”的规则试图说明的是,“在单个线程中,您的程序将运行 ,就像 一样。它是按照您编写的确切顺序执行的。我们可能会更改幕后的顺序,但我们要确保这些都不会改变输出。

    到现在为止还挺好。为什么它不能跨多个线程做同样的事情?在多线程编程中,Java 不够聪明,无法自动完成。对于某些操作(例如加入线程,启动线程,使用锁(监视器)时等),但对于其他操作,您需要明确告诉它不要进行会改变程序输出的重新排序(例如 volatile 标记在领域,使用锁等)。

    笔记:
    关于“发生在关系之前”的快速附录。这是一种奇特的说法,无论重新排序 Java 可能会做什么,A 都将在 B 之前发生。在我们奇怪的后炖示例中,“第 1 步和第 3 步发生在第 4 步之前“倒入鸡蛋和牛奶”。例如,“第 1 步和第 3 步不需要先发生关系,因为它们不以任何方式相互依赖”

    关于评论的附加问题和回复

    首先,让我们确定“时间”在编程世界中的含义。在编程中,我们有“绝对时间”的概念(现在世界上的时间是多少?)和“相对时间”的概念(从 x 过去了多少时间?)。在理想的世界中,时间就是时间,但除非我们有内置的原子钟,否则必须不时修正绝对时间。另一方面,对于相对时间,我们不想要更正,因为我们只对事件之间的差异感兴趣。

    在 Java 中, System.currentTime()处理绝对时间和 System.nanoTime()处理相对时间。这就是为什么nanoTime 的Javadoc 指出,“此方法只能用于测量耗时,与系统或挂钟时间的任何其他概念无关”。

    实际上, currentTimeMillis 和 nanoTime 都是 native 调用,因此编译器实际上无法证明重新排序是否不会影响正确性,这意味着它不会重新排序执行。

    但是让我们想象一下,我们想要编写一个编译器实现,它实际上查看 native 代码并在合法的情况下重新排序所有内容。当我们查看 JLS 时,它告诉我们的只是“只要无法检测到任何东西,您就可以重新排序”。现在作为编译器编写者,我们必须决定重新排序是否会违反语义。对于相对时间 (nanoTime),如果我们重新排序执行,它显然是无用的(即违反语义)。现在,如果我们为绝对时间 (currentTimeMillis) 重新排序会违反语义吗?只要我们可以限制从世界时间的来源(比方说系统时钟)到我们决定的任何内容(例如“50ms”)*之间的差异,我说不。对于以下示例:
    long tick = System.currentTimeMillis();
    result = compute();
    long tock = System.currentTimeMillis();
    print(result + ":" + tick - tock);

    如果编译器能证明 compute()小于我们可以允许的系统时钟的最大偏差,那么重新排序如下是合法的:
    long tick = System.currentTimeMillis();
    long tock = System.currentTimeMillis();
    result = compute();
    print(result + ":" + tick - tock);

    因为这样做不会违反我们定义的规范,因此不会违反语义。

    您还问为什么这不包括在 JLS 中。我认为答案是“保持 JLS 简短”。但我对这个领域了解不多,所以你可能想为此提出一个单独的问题。

    *:在实际实现中,这种差异取决于平台。

    关于java - Java并发中 "program order rule"的解读,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15654276/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com