模型出错,重下好多次了,检查游戏爱奇艺缓存数据出错完整性没问题。怎么办

新人教学,验证本地游戏文件的完整性,解决游戏bug~~_csgo吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0可签7级以上的吧50个
本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:395,467贴子:
新人教学,验证本地游戏文件的完整性,解决游戏bug~~
很多人玩着玩着就会出现各种各样的莫名错误,这个时候,大多验证一下本地游戏的完整性就能解决,也有很多人安装过ui等插件,搞的游戏界面乱七八糟,验证一下本地文件,也可以恢复游戏到原始状态~~
废话不多说 上图~~右键 steam ,选择 库 在 库 中找到 csgo ,右键
选择 属性 属性 里面找到 本地文件 选项
然后 找到 下面的 验证缓存的完整性开始验证本地文件验证完成不知道为啥,我每次验证都会提示我下载一个4.1M的文件,好像是一个跟dx有关的更新,每次验证都出现~~每次验证后都提示我安装这个东西最后发一张
我为啥 要验证我的呢,因为这个~~~tmd,有天理没有啊,今天早上 刚刚匹配一把,接着就 提示我 什么检测文件失效,大退重启都不管用,我就放弃了,结果,你妈 冷却7天啊,天理何在呀!!!!然后,我没法匹配了,蛋疼的无聊 就验证本地文件……
第一次打高文和第一次打...
刚才看打折在steam上买...
3D双端东方魔幻网游「大青云」勾魂公测,穿越逆转,封神故事,全新演绎!
我总结下 匹配失败的原因,可能是因为 我开了 netpas 的缘故~~,最近我被冷却 2回了,玩 经典的老图没事,但是 玩新地图,就莫名的掉出服务器,我就怀疑是 vpn 的缘故,不开vpn ,几乎就是 300+ 的ping ,开了vpn ,有时能 100 ping ,有时也不怎么管用 也得 将近 300 的ping~~
7 天 冷却,这下一个礼拜 不能玩匹配了……
我还想 刷一下 勋章 呢~~~
再 发一张 昨天 开的箱子,聊以自慰吧~~好歹 也是个 暗金呀~~
可惜不是 新出厂~~~~
前排,顺便出售花生,瓜子,咸瓜子,淡瓜子,沙发、板凳、小、、可乐、叉烧包、营养快线红、烧鸡翅、牛奶、、、、、、小喇叭、小手拍、口哨、雨衣、小红旗、、瓦块、、、、、、、、矿泉水、爽歪歪、乳娃娃、娃哈哈、、、、、、干脆面、、、、、、、、、香蕉、、露露、花生、核桃、、、、、、蛋挞、口香糖、、、、蛋糕、妙脆、、、、西酸奶、、、、、、、、、、香蕉、干、、、冰棍、、、四个圈、、、、、、、、、柠檬奶油、、、、搅、棉花糖、、等!!!!!!!!
这都用教- =
能解决不要检验缓存的完整性就上游戏的方法吗?每次上游戏都要检验太麻烦了
我老是被屏蔽 这次验证完 说一个文件验证失败 要重新装吗?
按楼主说的验证完后 下了那个东西可以玩了但是半小时后又被弹出来了 在验证又是下个东西·~有什么具体可以解决的吗?
我的也是,郁闷死了。每次都要验证,directX方面的
在职研究生报名入口,在职研究生名校报名
我每次进游戏都是这样、求帮助
每次进游戏都安装的,试试下面方法:All you need to do is to go to your CS:GO folder under /steamapps/common, then go to &_installer& folder, click right and make a new folder, then select all the files except:DSETUP.dlldsetup32.dlldxsetupand put them in the new folder that you have created.Now run the game through steam, it will install
again just for once, and it will never do it again.简单翻译:你要做得是,进入/steamapps/common/csgo目录,然后进入_installer目录,鼠标右键建立新目录,然后选择除了下面三个文件以外的所有文件:DSETUP.dlldsetup32.dlldxsetup将他们放到新建的目录里。现在通过steam运行csgo,将仅安装一次,以后将不会再自动安装。注:这是网上找到的方法,据论坛反馈是有效的,有问题的朋友可以试试看,不行再找其他方法。
玩了一年多了,这一周第一次出现了这种情况-0 -,然而楼上方法的没有解决问题。求支援!!!ps:半年前装WIN10,但是一直没出问题。
问一下,我刷新不出社区服务器怎么办
贴吧热议榜
使用签名档&&
保存至快速回贴EAC检测到文件夹被修改,请验证游戏的完整性_黎明杀机吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0可签7级以上的吧50个
本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:78,593贴子:
EAC检测到文件夹被修改,请验证游戏的完整性
求大神解答,问题我昨晚还在网吧玩了一整晚,今天中午在别的网吧就这样了
删除EAC那个文件夹重新验证也不行,这究竟什么鬼啊
难道是王八的问题?能解决吗?麻蛋游戏 玩两把都难
操操操操操操
验证码都没有 玩毛线啊...
今天更新游戏后,大部分...
在游戏文件夹 music里面...
我的雷达怎么看不见了...
我已经下载好显示已安装...
RT,就像这样。更加严重...
由于MD CD游戏内存较大...
重开十几次了,有谁一样...
1L防吃。 话说这个插件...
如题今天发现现在的游戏...
3D双端东方魔幻网游「大青云」勾魂公测,穿越逆转,封神故事,全新演绎!
别沉啊 求大神
大神何在啊?
难道就我一个人狗带了吗?
玩这个游戏真累,心态炸了
还是在自家电脑玩吧
验证完整性,然后重启电脑就可以了
验证一下完整性就行了,在网吧也遇到过这种情况,好像不用重启吧
在职研究生报名入口,在职研究生名校报名
不行的 我也是这种情况 家里玩好好的 网吧就不行
网吧自带防火墙屏蔽了EAC
我也一样的。不过已经好了
我也是这个问题呀,到现在还有找到有效的途径,也不到到底是什么原因。
我给你们个办法,在网吧可能无效,如果是在家里的,也许可以。请看16楼
属性浏览本地文件找到EAC文件
全名不清楚
就是有大写英文EAC的 把这个文件先复制一份到桌面属性 更新 里面 关闭云同步然后删除那个文件属性 验证完整性然后上
如果没出现问题了
进去随便点几个血网继续 属性 打开云同步
登录 如果进的去那就没问题了。
下个加速器秒进
来个简单点的方法 不要下在系统盘里 把原来的游戏内容从里删除重下 换个盘装就ok了
验证本地缓存完整性
给你们顶顶别沉
这个 好像有位兄弟说
把自家steam 一起 拷贝去网吧就可以了
等于能玩的网吧的steam拷贝过去 我还没试过
等大更新完了 我全部重新备份再给你们试下
我也是,我用的自己笔记本玩的,重做了个系统就玩不了了,刚进地图就提示eac,烦死了。。。没改过存档没改过血点,真是服了
两种可能,第一种BUG了第二种有人用你的机子的时候你号保留然后他给你改了。。。
贴吧热议榜
使用签名档&&
保存至快速回贴深入Java内存模型 - ImportNew
| 标签: ,
你可以在网上找到一大堆资料让你了解JMM是什么东西,但大多在你看完后仍然会有很多疑问。happen-before是怎么工作的呢?用volatile会导致缓存的丢弃吗?为什么我们从一开始就需要内存模型?
通过这篇文章,读者可以学习到足以回答以上所有问题的知识。它包含两大部分:第一部分是硬件层次的大体架构,第二部分是深入OpenJdk源代码和实现。因此,即使你没有太深入Java,你可能也会对第一部分感兴趣。
硬件相关的东西
搞硬件的工程师一直在努力地优化他们产品的性能,使我们可以获取更多的代码外的高性能部件。然而,它带来的问题是:当你的代码在运行时,你并不能直观地查看它是运行在什么场景下。有着无数硬件细节被抽象化。而抽象往往意味着容易有。
处理器缓存
对主存的请求是一项昂贵的操作,即使是在现代机器上,在执行的时候也会花上百纳秒的时间。然后,其他操作的执行时间,不同于主存的访问,其发展就显缓慢。这个问题通常被称为,而最明显的解决方案就是引入缓存。简单来说,处理器对它经常访问的主存数据保存一份拷贝。你可以在深入阅读不同的缓存架构,我们将会继续另外一个问题:保持缓存最新。
很明显,当我们只有一个执行部件(从现在开始这里指处理器)时是没问题的,但当你拥有多于一个时,事情会变得复杂。
如果A缓存了某些值,处理器A怎么知道处理器B已经修改了它们呢?
或者,更一般地说,你怎么保证缓存一致性
为了保存内存状态的一致性,处理器需要进行交互。那种交互的规则称之为缓存一致性协议(cache coherency protocol)
缓存一致性协议
现在有着很多不同的协议,不同的硬件厂商,甚至同一个厂商的不同产品线都会有所不同。尽管有着各种各样的区别,但大部分协议都有着很多共同点,这也是我们需要深入MESI的原因。然而,它并没有给读者一个所有协议的完整概述。有一些协议(例如)是完全不一样的。我们不准备深入他们。
在MESI中,每一个缓存条目都会属于以下状态之一:
无效(Invalid)缓存不再拥有该条目
独占(Exclusive)这个条目只存在于这个缓存,没有被修改
已修改(Modified)处理器已经修改过这个值,但还没有写回主存或者发送给其他处理器
共享(Shared)多于一个处理器的缓存拥有该条目
状态之间的转换是通过发送特定的协议消息。具体的消息类型关系不大,所以在本文忽略了。你可以通过很多其他的资料去深入了解它们。我会推荐
讽刺的是:当我们深入时,消息被用于并发修改状态。这是个问题。那么那些讨厌Actor Model的人怎么办?
MESI优化和他们引入的问题
在还没有说到细节时,我们知道消息的传递是需要时间的,它使得状态切换有更多的延迟。重要的是我们也需要意识到某些状态的切换需要特殊的处理,可能会阻塞处理器。这些都将会导致各种各样的稳定性和性能问题。
存储缓存(Store Bufferes)
如果你需要对一个在缓存中的共享的变量进行写入,你需要发送一个失效(Invalidate)消息给它的所有持有者,并且等待它们的确认。处理器在这段时间间隔内会阻塞,这是一个不爽的事情,因为这个时间的要求比普通执行一个指令要长得多。
在现实生活中,缓存条目不只包含一个变量。这个被划分出来的单元是一个缓存链,通常包含多于一个变量,并且很多是64字节大小的。
它会导致有趣的问题,例如
为了避免这种时间的浪费,Store Bufferes被引入使用。处理器把它想要写入到主存的值写到缓存,然后继续去处理其他事情。当所有失效确认(Invalidate Acknowledge)都接收到时,数据才会最终被提交。
有人会想到这里有一些隐藏的危险存在。简单的一个就是处理器会尝试从存储缓存(Store buffer)中读取值,但它还没有进行提交。这个的解决方案称为Store Forwarding,它使得加载的时候,如果存储缓存中存在,则进行返回。
第二个陷阱是:保存什么时候会完成,这个并没有任何保证。考虑一下下面的代码:
void executedOnCpu0() {
value = 10;
finished =
void executedOnCpu1() {
while(!finished);
assert value == 10;
试想一下开始执行时,CPU 0保存着finished在Exclusive状态,而value并没有保存在它的缓存中。(例如,Invalid)。在这种情况下,value会比finished更迟地抛弃存储缓存。完全有可能CPU 1读取finished的值为true,而value的值不等于10。
这种在可识别的行为中发生的变化称为重排序(reordings)。注意,这不意味着你的指令的位置被恶意(或者好意)地更改。
它只是意味着其他的CPU会读到跟程序中写入的顺序不一样的结果。
执行失效也不是一个简单的操作,它需要处理器去处理。另外,存储缓存(Store Buffers)并不是无穷大的,所以处理器有时需要等待失效确认的返回。这两个操作都会使得性能大幅降低。为了应付这种情况,引入了失效队列。它们的约定如下:
对于所有的收到的Invalidate请求,Invalidate Acknowlege消息必须立刻发送
Invalidate并不真正执行,而是被放在一个特殊的队列中,在方便的时候才会去执行。
处理器不会发送任何消息给所处理的缓存条目,直到它处理Invalidate
也正是那些优化的情况会导致这种跟直觉不符的结果。让我们看回代码,假设CPU 1存有Exclusive状态的value。这里有一张图表,表示其中一种可能的执行情况:
同步是很简单容易,不是吗?问题在于steps (4) – (6)。当CPU 1在(4)接收到Invalidate时,它只是把它进行排列,并没有执行。CPU 1在(6)得到Read Response,而对应的Read在(2)之前就被发送。尽管这样,我们也没有使value失效,所以造成了assertion的失败。如果那个操作早点执行就好了。但,唉,这该死的优化搞坏了所有事情!但从另一方面考虑,它给予了我们重要的性能优化。
那些硬件工程师没办法提前知道的是:什么时候优化是允许的,而什么时候并不允许。这也是他们为什么把这个问题留给我们。它同时也给予我们一些小东西,标志着:“单独使用它很危险!用这个!”
硬件内存模型
软件工程师在出发和巨龙搏斗时被授予的魔法剑并不是真正的剑。同样,那些搞硬件的家伙给我们的是写好的规则。他们描述着:当这个(或其他)处理器执行指令时,处理器能够看见什么值。我们能够像符咒一样把他们分类成Memory Barriers。对于我们的MESI例子,它描述如下:
Store Memory Barrier(a.k.a. ST, SMB, smp_wmb)是一条告诉处理器在执行这之后的指令之前,应用所有已经在存储缓存(store buffer)中的保存的指令。
Load Memory Barrier (a.k.a. LD, RMB, smp_rmb)是一条告诉处理器在执行任何的加载前,先应用所有已经在失效队列中的失效操作的指令。
因此,这两个方法可以防止我们之前遇到的两种情况。我们应该使用它:
void executedOnCpu0() {
value = 10;
storeMemoryBarrier(); // Mighty Spell!
finished =
void executedOnCpu1() {
while(!finished);
loadMemoryBarrier(); // I am a Wizard!
assert value == 10;
哈!我们现在安全了。是时候来写一些高性能并且正常的并发代码了!
啊,等等。它甚至不能编译,显示找不到方法。真糟糕。
一次编写,处处运行
上面的那些缓存一致性协议,memory barriers,内存清除(dropped caches)和类似的东西看起来都是恶心的平台相关的东西。Java开发人员不应该关心这些东西。毕竟Java内存模型没有重排序的概念。
如果你没有完全理解上面的最后一段,你不应该继续往下阅读了。一个好的建议是先去学习一下JMM相关的知识。一个很好的入门教程应该是这篇
但应该会有更抽象层次的重排序。你应该会有兴趣看看JMM是怎么映射到硬件模型的。让我们从一个简单的类开始:()
有许多不同的场景供我们去了解究竟发生了什么:PrintAssembly很有趣,可以看到编译器正在做什么,而不用再去问别人,地告诉你缓存被丢序了等等。我决定深入看看OpernJDK的C1(client编译器)。由于client编译器很少用在真实的应用中,作为教学用是一个好选择。
我使用的是jdk8,版本号为。在其他版本有可能会不一样。
如果你以前从来就没有深入过OpenJDK的源码(或者你有),你很难找你很感兴趣的地方在哪里。一个缩小查找范围的方法是取得你感兴趣的字节码指令,大概看一下它。好的,我们就这样做:
$ javac TestSubject.java && javap -c TestSubject
void executedOnCpu0();
0: aload_0
// Push this to the stack
10 // Push 10 to the stack
3: putfield
#2 // Assign 10 to the second field(value) of this
6: aload_0
// Push this to the stack
7: iconst_1
// Push 1 to the stack
8: putfield
#3 // Assign 1 to the third field(finished) of this
11: return
void executedOnCpu1();
0: aload_0
// Push this to the stack
1: getfield
#3 // Load the third field of this(finished) and push it to the stack
10 // If the top of the stack is not zero, go to label 10
// One more iteration of the loop
10: getstatic
#4 // Get the static system field $assertionsDisabled:Z
33 // If the assertions are disabled, go to label 33(the end)
16: aload_0
// Push this to the stack
17: getfield
#2 // Load the second field of this(value) and push it to the stack
20: bipush
10 // Push 10 to the stack
22: if_icmpeq
33 // If the top two elements of the stack are equal, go to label 33(the end)
#5 // Create a new java/lang/AssertionError
// Duplicate the top of the stack
29: invokespecial #6 // Invoke the constructor (the
32: athrow
// Throw what we have at the top of the stack (an AssertionError)
33: return
你不应该单单看了字节码就开始猜想你程序的执行(或者底层操作)。当JIT编译器编译它时,代码会跟现在看到的基本两样。
我们做这个的目的就是为了了解它们是为谁工作的。
这些有两个有趣的事情:
许多人都会忘记:断言在默认情况下是关闭的。用-ea来启用他们。
我们查找的名字:getfield和putfield
我们看到,用于加载和保存volatile和普通属性的指令是一样的。所以,一个好办法就是找到编译器是在哪里知道一个属性是否是volatile。随便看了一下,我们的目光停留在share/vm/ci/ciField.hpp文件。有趣的方法是
bool is_volatile() { return flags().is_volatile(); }
所以,我们现在的任务就是找到处理加载和保存属性的方法,并且通过结果分析调用上面这个方法的代码层次关系。Client编译器在Low-Level Intermediate Representation(LIR)层上处理它们,代码在文件:share/vm/c1/c1_LIRGenerator.cpp
C1中间展示
我们由保存开始。我们深入的方法是void LIRGenerator::do_StoreField(StoreField* x),它在行。我们看到的第一个显眼的操作是:
if (is_volatile && os::is_MP()) {
__ membar_release();
很好,一个memory barrier!两个下划线是一个宏,可以被展开为gen()-&lir()-&,另外,被调用的方法定义在share/vm/c1/c1_LIR.hpp:
void membar_release() { append(new LIR_Op0(lir_membar_release)); }
所以,发生的事情就是我们对我们的展示添加多了一个操作ir_membar_release
被调用的方法有着平台相关的实现。给x86(cpu/x86/vm/c1\_LIRGenerator\_x86.cpp)的很简单:对于64位的属性,我们尝试一些技巧性的方法来保证写入的原子性。因为。这有点过时,但会在的时候更新。最后一个我们需要看的是在方法最后的又一个memory barrier。
if (is_volatile && os::is_MP()) {
__ membar();
void membar() { append(new LIR_Op0(lir_membar)); }
这就是保存的处理。
加载在源代码稍微底层点,几乎没有包含任何新东西。它同样有一些技巧性的方法来处理long和double的原子性,在加载完成后会添加lir_membar_acquire。
注意,我故意省略一些跟这关联的东西,例如:GC相关的指令。
Memory Barrier类型和抽象层次(Abstraction Levels)
这个时候,你肯定会想release和acquire memory barriers是什么东西,因为我们到现在都还没介绍。这完全是因为我们所看到的store和load memory barriers是在MESI模型中的操作,然后我们现在正在看的是在其上几层的抽层层次(或者任何其他的内存一致性协议)。在这一层,我们有不同的术语。
考虑到我们有两种类型的操作,Load和Store,我们拥有四种组合:LoadLoad,LoadStore,StoreLoad,StoreStore。因此也很方便的得到四种相同名称的memory barriers。
如果我们有一个XY memory barrier,它表示所有的在barrier前的X操作必须比在barrier后的任意Y操作提前完成它们的操作。
例如,所有的在StoreStore barrier前的Store操作必须比barrier后的任意Store操作早完成。是关于这个主题的一本好书。
有些人会疑惑,认为memory barriers接收一个变量作为参数,然后阻止跨进程间对该变量的重排序。
Memory barriers只能用在一个线程内。恰当地组合使用它们,你可以保证其他线程在加载这些值的时候看到一致的情况。一般地说,JMM的所有抽象都是由正确的组合memory barriers来实现的。
还有一些Acquire和Release语义。一个拥有release语义的write操作要求所有在它之前的内存操作都必须在它执行前完成。而read-acquire操作是相反的情况。
有人会发现Release Memory Barrier可以通过LoadStore|StoreStore的结合来实现,而Acquire Memory Barrier是LoadStore|LoadLoad。StoreLoad就是我们上面看到的lir_membar。
生成汇编代码
现在我们已经找到了IR和它的memory barriers,我们可以深入本地实现层了。所有的处理都在share/vm/c1/c1_LIRAssembler.cpp文件内:
case lir_membar_release:
membar_release();
memory barriers是平台相关的,对于x86平台,我们看cpu/x86/vm/c1_LIRAssembler_x86.cpp文件。我们发现x86在内存模型架构上相当严格,因此大部分的memory barriers都是没有处理的。
void LIR_Assembler::membar_acquire() {
// No x86 machines currently require load fences
// __ load_fence();
void LIR_Assembler::membar_release() {
// No x86 machines currently require store fences
// __ store_fence();
然而这并不是所有:
void LIR_Assembler::membar() {
// QQQ sparc TSO uses this,
__ membar( Assembler::Membar_mask_bits(Assembler::StoreLoad));
(我们深入cpu/x86/vm/assembler_x86.hpp)
// Serializes memory and blows flags
void membar(Membar_mask_bits order_constraint) {
if (os::is_MP()) {
// We only have to handle StoreLoad
if (order_constraint & StoreLoad) {
// All usable chips support &locked& instructions which suffice
// as barriers, and are much faster than the alternative of
// using cpuid instruction. We use here a locked add [esp],0.
// This is conveniently otherwise a no-op except for blowing
// Any change to this code may need to revisit other places in
// the code where this idiom is used, in particular the
// orderAccess code.
addl(Address(rsp, 0), 0);// Assert the lock# signal here
因此,对于每一个volatile写入,我们必须使用代价较大的形式为lock addl $0x0,(%rsp)的StoreLoad barrier。它强制要求我们去执行所有的挂起的保存,并且有效地保证其他线程可以很快地看到最新的值。而对于volatile读取,我们没有使用其他的barriers。然而我们不能想着。
我们应该清楚虽然barriers没有生成汇编代码,但它仍然存在在IR中的。如果他们被可以修改代码的组件(这里指编译器)忽略,那将会是一个类似的bug。
完整性检查
虽然通过查看OpenJDK源代码来学习是很好的,所有真正的科学家都这样,并且测试他们的理论。我们还是不要搞特例,同样来学习吧。
Java并发很有趣
好消息是我们不需要再重造轮子,因为已经有工具来长时间执行代码,并且把输出完全聚合起来。它同样帮我们做了很多没什么意义工作,包括那些我们根本没意识到我们必须要去做的。
与其同时,jcstress已经拥有了我们需要的充分的。
static class State {
// acq/rel var
public void actor1(State s, IntResult2 r) {
public void actor2(State s, IntResult2 r) {
r.r1 = s.y;
r.r2 = s.x;
我们有一个线程,用来执行保存,而另外一个执行读取,然后会输出相应的状态。框架已经帮我们聚合了需要的结果,这些结果满足一定的。我们对由第二个线程得到的两个可能出现的结果感兴趣:[1,0]和[1,1]。在这两种情况中,它加载了y == 1,但看不到写入给x的值,或者加载了一个并不是y写入时的最新值。根据我们的理论,这种情况的出现原因在于没有volatile标识符。让我们看一下:
$ java -jar tests-all/target/jcstress.jar -v -t &.*UnfencedAcquireReleaseTest.*&
Observed state
Occurrence
Expectation
Interpretation
----------------------------------------------------------------------------------------------------------------
ACCEPTABLE
Before observing releasing write to, any value is OK for $x.
ACCEPTABLE
Before observing releasing write to, any value is OK for $x.
ACCEPTABLE
Before observing releasing write to, any value is OK for $x.
ACCEPTABLE
Before observing releasing write to, any value is OK for $x.
ACCEPTABLE_INTERESTING Can read the default or old value for $x after $y is observed.
ACCEPTABLE
Can see a released value of $x if $y is observed.
ACCEPTABLE
Can see a released value of $x if $y is observed.
因此,中有65960次 (≈ 0.07%),第二个线程得到了y == 1 && x == 0,这也证明了重排序是确实有运行的。
PrintAssembly的乐趣
我们需要检查的第二件事情是:我们是否正确地预测生成的汇编代码。因此,我们添加了很多所需代码的调用,为了方便结果演示,取消了inlining,开启了断言(assertoins),并且跑在client模式下。
$ java -client -ea -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:MaxInlineSize=0 TestSubject
# {method} 'executedOnCpu0' '()V' in 'TestSubject'
0xd07405c: movl
$0xa,0xc(%rsi)
0xd074063: movb
$0x1,0x10(%rsi)
0xd074067: lock addl $0x0,(%rsp)*putfield finished
- TestSubject::executedOnCpu0@8 (line 15)
# {method} 'executedOnCpu1' '()V' in 'TestSubject'
0xd061126: movzbl 0x10(%rbx),%r11*getfield finished
- TestSubject::executedOnCpu1@1 (line 19)
0xd06112b: test
%r11d,%r11d
啊,就跟预想的一样!是时候完成了。
让我来提醒你那些你现在应该可以回答的问题:
它是怎么实现的?
使用volatile会导致缓存被丢弃吗?
为什么我们一开始就需要内存模型?
你觉得你可以回答这些?欢迎留言!
P.S 这是我早前的的翻译,感谢。
原文链接:
- 译文链接: [ 转载请保留原文出处、译者和译文链接。]
关于作者:
(新浪微博:)
除了第一种方式, 喜欢用浏览器简单测一下什么的人感觉很蛋疼
关于ImportNew
ImportNew 专注于 Java 技术分享。于日 11:11正式上线。是的,这是一个很特别的时刻 :)
ImportNew 由两个 Java 关键字 import 和 new 组成,意指:Java 开发者学习新知识的网站。 import 可认为是学习和吸收, new 则可认为是新知识、新技术圈子和新朋友……
新浪微博:
推荐微信号
反馈建议:@
广告与商务合作QQ:
– 好的话题、有启发的回复、值得信赖的圈子
– 写了文章?看干货?去头条!
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 活跃 & 专业的翻译小组
– 国内外的精选博客文章
– UI,网页,交互和用户体验
– JavaScript, HTML5, CSS
– 专注Android技术分享
– 专注iOS技术分享
– 专注Java技术分享
– 专注Python技术分享
& 2017 ImportNew

我要回帖

更多关于 office文档缓存时出错 的文章

 

随机推荐