- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图了解 Java 内存模型,但一直未能了解有关 CPU 缓存的要点。
据我所知,在 JVM 中我们有以下位置来存储本地变量和共享变量:
local variables -- on thread stack
shared variables -- in memory, but every CPU cache has a copy of it
所以我的问题是:为什么将局部变量存储在堆栈上,并将共享变量(缓存)存储在CPU缓存中?为什么不反过来(假设 CPU 缓存太昂贵而无法存储两者),我们将局部变量缓存在 CPU 缓存中,而只从内存中获取共享变量?这是Java语言设计的一部分还是计算机体系结构的一部分?
进一步:“CPU 缓存”听起来很简单,如果多个 CPU 共享一个缓存会怎样?而在具有多级缓存的系统中,共享变量的副本将存储在哪一级缓存中?此外,如果超过 1 个线程在同一个 CPU 核心中运行,是否意味着它们共享同一组缓存的共享变量,因此即使共享变量未定义 volatile
,变量的访问对于同一 CPU 上运行的其他线程仍然立即可见?
最佳答案
“本地”和“共享”变量在代码上下文之外毫无意义。它们不会影响状态的缓存位置,甚至不会影响状态的缓存。思考或推理你的状态存储在哪里甚至没有用; JMM 存在的全部原因是这样的细节(这些细节因架构而异)不会暴露给程序员。通过依赖低级硬件细节,您会提出有关 JMM 的错误问题。它对您的应用程序没有用处,它会使应用程序变得脆弱、更容易损坏、更难以推理并且更不易移植。
也就是说,一般来说,您应该假设任何程序状态(如果不是所有状态)都有资格被缓存。事实上,缓存什么并不重要,任何东西都可以,无论是原始类型还是引用类型,甚至是由多个字段封装的状态变量。无论线程运行什么指令(这些指令也因体系结构而异 - 请注意!),这些指令默认返回 CPU 来确定哪些内容与缓存相关以及哪些内容不缓存;程序员自己不可能做到这一点(尽管它可能可能影响状态变量可能被缓存的位置,看看 false sharing 是什么)。
同样,我们还可以对 x86 进行一些更多的概括,即 Activity 的基本类型可能放在寄存器中,因为 P/ALU 将能够以最快的速度使用它们。不过其他的都可以。如果原语是核心本地的,则它们有可能被移动到 L1/2 缓存,当然它们可能会很快被覆盖。如果 CPU 认为将来会发生上下文切换,则可能会将状态变量放在共享的 L3 上,或者不会。硬件专家需要对此做出回应。
理想情况下,状态变量将存储在距离处理器单元最近的高速缓存(寄存器、L1/2/3,然后是主存储器)中。但这是由 CPU 决定的。在 Java 级别推理缓存语义是不可能的。即使启用了超线程(我不确定 AMD 等效项是什么),线程也不允许共享资源,即使如此,如果可以的话,请记住可见性并不是与共享状态变量相关的唯一问题;在处理器执行流水线操作的情况下,您仍然需要适当的指令来确保正确的顺序(即使在您摆脱 CPU 上的读/写缓冲之后),无论是 hwsync 还是适当的围栏或其他。
同样,推理缓存的属性是没有用的,因为 JMM 会为您处理该属性,而且因为无法确定缓存的位置/时间/内容。此外,即使您确实知道地点/时间/内容问题,您仍然无法推理数据可见性;无论如何,所有缓存都以相同的方式处理缓存数据,您将需要依赖处理器更新 ME(O)SI 状态之间的缓存状态、指令排序、加载/存储缓冲、回写/直写等。 .并且您还没有处理可能发生在操作系统和 JVM 级别的问题。同样,幸运的是,JDK 允许您使用基本工具,例如 volatile
、final
和原子,这些工具在所有平台上一致工作,并生成可预测且简单的代码(呃)来推理。
关于java - 为什么共享变量会缓存在CPU缓存中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47965438/
只是想知道是否有可能找出谁从 Windows 共享中读取了文件(最好使用 .NET,但 win32 native 可以)? 我想做的是创建类似 awstats 的东西对于 Windows 共享,这样我
是否可以列出 Intent.ACTION_SEND ?我的意思是我需要知道是否有人通过 action_send 在 Facebook 上分享或在 Twitter 上发推文。 最佳答案 也许你想要一个更
我正在使用 Google Apps 应用程序。实际上,我想在不使用密码的情况下访问另一个 ID。我使用了 OAuth,它运行良好。但我无法分享特定人的日历。我尝试了以下代码。 GoogleOAuthP
我怎样才能只创建模拟器...可能吗?我知道,设备需要分发证书。 最佳答案 您只需将应用程序目录从 iPhone 模拟器复制到另一个实例/操作系统版本,它就应该可以工作。 因此,如果您想分发 3.1.3
我想使用多阶段构建来避免每次构建应用程序时都下载我的 Java 项目所需的所有 Maven 依赖项。 我正在考虑在第一阶段解决 Maven 依赖项,然后在第二阶段构建应用程序,这将需要访问在前一阶段下
我正在寻找保护用户下载内容的初步想法。用户下载充满有趣资源的 zip 文件,这些资源被提取到本地文件系统中以供应用程序使用。我的目标是防止用户通过互联网将下载的资源共享给其他用户(假设他们获得了对文件
我想知道在具有移动和桌面版本的网站上共享身份验证、 session 管理等的最佳方法是什么。我们正在运行 Tomcat,并且更愿意将移动站点和桌面站点的应用程序保持在不同的节点上。 我看过类似的帖子,
我发现了这个单例的实现。我怎样才能创建指向它的指针或共享指针?` 为什么这不起作用?自动测试 = Singleton::Instance(); class Singleton { public: st
我有一个 heroku 项目,我想与其他人分享。作为the instructions describe ,我使用 virtualenv 来管理环境和依赖项。有没有办法在新机器上从 requiremen
Maven 将所有 jar 存储在本地存储库 ~/.m2/repository/ 下。用户多时占用空间大。 那么,是否可以由多个用户共享这个本地存储库,或许在不同的目录结构下? 最佳答案 简单的回答
为什么共享 worker 在重新加载页面时死了?应该是复活了我该如何解决这个问题? 重装前 重新加载后(在example.com上按F5) parent worker var port = new S
我正在开发多个小型应用程序,这些应用程序将共享通用和共享模块和 Assets 。 关于如何创建项目结构的部分在这里回答:https://stackoverflow.com/a/61254557/135
我在 RHEL 上安装了 jenkins (localhost:8080),我能够成功地构建代码 现在,我想设置主/从代理。 我的笔记本电脑将充当“Master Jenkins”,而我同事的笔记本电脑
我有这种方法可以根据我使用的 EXTRA_STREAM 共享文本文件或图片。我有这两个我可以选择 i.putExtra(Intent.EXTRA_STREAM, uri); i.putExtra(In
我正在使用 R 中的一个数据分析项目,我正在使用 R 中的敏感私有(private)数据进行一些逻辑和多级建模。我爱上了 。预订 包,我已经创建了一本关于我们的工作流程和分析管道的相当广泛的书。问题是
我正在构建的应用程序需要在 UITabBarController 框架内为多个 View (及其 subview )显示共享的自定义 UIToolbar。自定义工具栏的内容在所有 View 中都是相同
我有多个应用程序,我想共享相同的 eslint 配置: - project_root/ - app1/ - node_modules/ - eslint.rc
我有多个 Electron 应用程序。一个是主应用程序,其他几个功能应用程序。主应用程序上的按钮很少,这将导致功能应用程序打开。这里的问题是每个应用程序都有一个主进程,该进程导致要利用更多的CPU。是
我正在开发一个 Node.js 后端,它通过 websocket 与一些桌面客户端进行通信,而服务器端的通信是从 Web 前端发起的。一切正常,因为我将 SockJS Connection 实例存储在
我对托管多个网站的服务器上的多个用户帐户使用私有(private) SSH key 和无密码条目。 我为每个用户帐户使用相同的私钥。 (因为我很懒?或者那是“正确”的方式)。 我现在想授权该国不同地区
我是一名优秀的程序员,十分优秀!