Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java多线程同步关键字的用途_Java_Multithreading_Concurrency_Synchronization_Thread Safety - Fatal编程技术网

Java多线程同步关键字的用途

Java多线程同步关键字的用途,java,multithreading,concurrency,synchronization,thread-safety,Java,Multithreading,Concurrency,Synchronization,Thread Safety,从《Java in》一书中可以看出: 我们之所以使用synchronized这个词作为“requires temporary”的关键字 “独占访问”是指除了获取监视器外,JVM还重新读取 输入块时,主存储器中对象的当前状态。同样地, 当同步块或方法退出时,JVM将刷新任何修改的块或方法 将对象的状态返回到主内存 以及: 如果没有同步,系统中不同的CPU核可能看不到相同的数据 内存视图和内存不一致可能会损坏正在运行的系统的状态 这个程序,正如我们在ATM示例中看到的 它建议在输入同步方法时,从主存

从《Java in》一书中可以看出:

我们之所以使用synchronized这个词作为“requires temporary”的关键字 “独占访问”是指除了获取监视器外,JVM还重新读取 输入块时,主存储器中对象的当前状态。同样地, 当同步块或方法退出时,JVM将刷新任何修改的块或方法 将对象的状态返回到主内存

以及:

如果没有同步,系统中不同的CPU核可能看不到相同的数据 内存视图和内存不一致可能会损坏正在运行的系统的状态 这个程序,正如我们在ATM示例中看到的

它建议在输入同步方法时,从主存加载对象以保持内存一致性


但是没有同步关键字的对象也是这样吗?因此,在正常对象被修改的情况下,CPU的一个核心与主存同步,以便其他核心可以看到它?

首先,类似于其他未命中信息的情况,如:

Volatile应该让线程从RAM中读取值 禁用线程缓存

更多关于为什么不是这样的细节可以找到

可应用于以下语句的:

JVM还从主窗口重新读取对象的当前状态 输入块时的内存

当同步块或方法退出时,JVM将刷新任何 修改后的对象状态返回到主内存

在评论中指出以下内容,并允许我使用:

这在任何现代系统上都不会发生。从理论上讲,平台可能需要做这些事情来实现同步工作,但如果平台上不需要这些事情(并且它们不在您可能使用的任何平台上),则无法完成。 这些语句都是关于一个没有硬件同步的假设系统,可能需要这些步骤实际系统的硬件设计与这个简化的假设系统非常不同,需要做的事情也非常不同。(例如,它们通常只需要优化和内存屏障,而不需要刷新到主内存或读取。这是因为现代系统经过优化,并使用缓存来避免必须刷新到主内存或从主内存重新读取,因为主内存非常慢,因此现代CPU进行了硬件优化以避免这种情况。


现在回到你的问题:

但对于没有同步关键字的对象也是这样吗 一个CPU内核中普通对象被修改的情况是同步的 有主存让其他核心可以看到吗

TL;DR:这可能会发生,也可能不会发生;这取决于硬件以及对象是否从缓存中读取;但是,通过使用
同步化
,JVM确保它将被同步


更详细的答案

因此,在正常对象的情况下,在CPU的一个核心中被修改 与主存同步,以便其他核心可以看到它

为了保持简洁,无需同步它取决于执行代码的硬件体系结构(例如缓存协议),并且取决于读取/更新时对象是否在缓存中

如果体系结构强制核心中的数据始终与其他核心一致,则为是。访问缓存比访问主内存快得多,访问第一级缓存(例如,L1)也比访问其他级别快得多

因此,出于性能原因,通常当数据(例如,对象)从主存加载时,它会存储在缓存(例如,L1、L2和L3)中,以便在再次需要相同数据时更快地访问

缓存的第一级往往对每个核心都是私有的。因此,不同的核心可能在其私有缓存(例如,L1)中存储了“同一对象”的不同状态。因此,线程也可能正在读取/更新“同一对象”的不同状态


注意,我写了“同一个对象”因为概念上它是同一个对象,但实际上它不是同一个实体,而是从主存读取的同一个对象的副本。

另一个答案谈到缓存同步和内存层次结构的重要性,而
synchronized
关键字不控制对象的状态一个整体;相反,它是关于与该对象关联的锁的

Java中的每个对象实例都可以有一个关联的锁,该锁防止在锁上同步的那些块的多个线程同时运行。这在
This
实例或synchronized关键字(或类,如果是静态方法)的参数上是隐式的

虽然JMM语义表示该锁对象在缓存级别得到了适当的控制和可用,但这并不一定意味着该对象作为一个整体受到了保护;例如,当单个线程在同步块或方法中运行时,不处理从不同线程读取的字段

此外,Java内存模型还定义了“之前发生”关系,即您需要考虑的线程之间的数据更改如何变得可见,这就是为什么会出现“volatile”关键字和AtomicXxxx类型,包括var内存模型


<> P>所以当你谈到同步时,你需要意识到它只是拍摄对象锁的状态,而不是它所保护的对象内的状态。