gpt4 book ai didi

java - 根据 java 内存模型,synchronized 到底做了什么?

转载 作者:行者123 更新时间:2023-12-01 20:00:47 24 4
gpt4 key购买 nike

在阅读了一些有关 java 内存模型和同步的内容后,出现了一些问题:

Even if Thread 1 synchronizes the writes, then although the effect of the writes will be flushed to main memory, Thread 2 will still not see them because the read came from level 1 cache. So synchronizing writes only prevents collisions on writes. (Java thread-safe write-only hashmap)

Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads. (https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html)

第三个网站(抱歉,我找不到了)说,对任何对象的每次更改(它不关心引用来自哪里)都会在方法离开同步块(synchronized block)并建立时刷新到内存中发生在之前的情况。

我的问题是:

  1. 退出同步块(synchronized block)真正刷新回内存的是什么? (有些网站也说只有获得锁的对象才会被刷新。)

  2. 在这种情况下,happens-before-relaitonship是什么意思?进入 block 时将从内存中重新读取什么,什么不是?

  3. 锁如何实现此功能(来自 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html):

    All Lock implementations must enforce the same memory synchronization semantics as provided by the built-in monitor lock, as described in section 17.4 of The Java™ Language Specification:

    A successful lock operation has the same memory synchronization effects as a successful Lock action. A successful unlock operation has the same memory synchronization effects as a successful Unlock action. Unsuccessful locking and unlocking operations, and reentrant locking/unlocking operations, do not require any memory synchronization effects.

如果我关于所有内容都将被重新读取和刷新的假设是正确的,那么这是通过在锁定和解锁函数中使用同步块(synchronized block)来实现的(这也是大多数必要的),对吧?如果错了,这个功能如何实现?

提前谢谢您!

最佳答案

发生在关系之前是你必须理解的基本事情,如 the formal specification就按照这些来运作。 “冲洗”之类的术语是技术细节,可以帮助您理解它们,或者在最坏的情况下误导您。

如果线程执行操作 Asynchronized(object1) { … }内,后跟执行操作的线程 Bsynchronized(object1) { … }内,假设object1引用同一个对象,A 之间存在happens-before-relationshipB并且这些操作对于访问共享可变数据是安全的(假设没有其他人修改此数据)。

但这是一个有向关系,即B可以安全地访问A修改的数据。但当看到两个synchronized(object1) { … } block ,确保 object1是同一个对象,你还需要知道是否AB 之前执行或BA 之前执行,了解发生在关系之前的方向。对于普通的面向对象代码,这通常很自然,因为每个操作都会对其找到的对象的任何先前状态进行操作。

说到冲水,留下一个synchronized block 会导致刷新所有写入数据并输入 synchronized block 会导致重新读取所有可变数据,但没有 synchronized 的互斥保证在同一实例中,无法控制哪个发生在另一个之前发生。更糟糕的是,您无法使用共享数据来检测情况,因为在不阻塞其他线程的情况下,它仍然可以不一致地修改您正在操作的数据。

由于不同对象上的同步无法建立有效的happens-before关系,因此JVM的优化器不需要维持全局刷新效果。最值得注意的是,如果逃逸分析证明该对象永远不会被其他线程看到,那么今天的 JVM 将取消同步。

因此,您可以在对象上使用同步来保护对存储在其他位置(即不在该对象中)的数据的访问,但它仍然需要在同一对象实例上对同一共享数据的所有访问进行一致的同步,这使程序变得复杂逻辑,与简单地同步包含 protected 数据的同一对象相比。

<小时/>

volatile变量,如 Lock 使用的变量如果线程读取和写入相同的内容,则在内部也具有全局刷新效果 volatile变量,并使用该值形成正确的程序逻辑。这比 synchronized 更棘手。 block ,因为代码执行没有互斥,或者,您可以将其视为仅限于单个读取、写入或 cas 操作的互斥。

关于java - 根据 java 内存模型,synchronized 到底做了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48041892/

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