百科问答小站 logo
百科问答小站 font logo



是否有文档支持Java『volatile int i 在执行 i++ 的底层是非原子性的三步』的说法? 第1页

  

user avatar   bei-ji-85 网友的相关建议: 
      

volatile

A Java keyword used in variable declarations that specifies that the variable is modified asynchronously by concurrently running threads.



根本没写原子操作的事情


user avatar   s.invalid 网友的相关建议: 
      

原子性很昂贵的。


不要问“有没有文档支持volatile int i在执行i++时没有原子性”,而应该是“没有文档明确承诺原子性时,请一定要默认相关操作没有原子性”——包括从内存读入一个int到寄存器,哪怕这一个动作你都不能默认它有原子性(假如没有字节对齐,load i 还真有可能得分两次执行)。


补充一点:不要靠查汇编来自行得出结论,这是个错误的方法。


很多时候,某个版本、某种CPU的某个工作模式下得出的结论,在下一个版本、另一种CPU甚至同种CPU的不同工作模式下就是错的。

这是因为,现代编译器极其智能,可以根据上下文任意改变指令顺序甚至删除、合并指令——只要最终执行结果语义等价。类似的,CPU自己也可能乱序执行你的程序,只要语义等价。

这样做反而是极其有益的。灵活的执行策略才能允许编译器生成最高效的程序、让CPU因地制宜的根据实际情况实时选择最优执行方案。

你不应该依赖后面的细节。这相当于你要求编译器/CPU死板的生成和执行你的程序。而这反而是做不到的,因为编译器/CPU已经被设计成智能模式了,没人能保证它总是按上一次的方式执行。


但反过来却是有保证的。无论CPU还是编译器文档,它们都会向你承诺一些操作的语义——不管执行过程多么花样百出,这些语义是可以100%保证的。它是你唯一可以信赖的东西。


因此,正如Linus所说,把事情做对的方式只有两个:

其一是找到正式文档,确保文档中给了清晰无歧义的承诺;

其二是做大量的实验,尽可能覆盖市面上所有的CPU所有的工作模式、所有的软件环境以及所有的应用场景/传入参数,只有所有这些测试全都通过(或者少量未能通过)时,我们才可以说这个做法是有效的(同时还要列出哪些情况下会失效)——然后,每当软件更新/CPU升级,我们就不得不重复这些测试,这才能宣布我们的软件可以支持新的软硬件环境。


一般来说,写一个新软件、或者为旧软件添加新功能时,应该遵循策略一,不要依赖任何未经确认的假设,这样才可能写出健壮的程序。

而维护旧软件时,可能就不得不依赖策略二——但这种代码很容易搞成“屎山”,因此可能不得不想办法搞好隔离;同时尽量避免任何新代码依赖同样的假设(哪怕它已经被大量的使用/测试证明在大多数系统上工作的很好)。否则一旦在某个新环境出现了问题,改起来那可真是……




  

相关话题

  未来桌面操作系统的发展趋势是什么? 
  为什么 Python 工程师很少像 Java 工程师那样讨论垃圾回收? 
  天宫的操作系统是中文的吗? 
  为什么时效上具有明显优势的基数排序(radix sort)没有快速排序流行? 
  怎样算是学好了 Java? 
  不想随大流,怎么选择有个性的操作系统? 
  使用微软历代 Windows 版本是怎样的一番体验? 
  为什么 Google 要赔 Oracle 88 亿? 
  你什么时候对 Java 感到绝望? 
  你怎么看待华为与它的鸿蒙OS? 

前一个讨论
特斯拉选择 Linux 作为车载系统的原因是什么?
下一个讨论
2021年了,你还在玩游戏《闪耀暖暖》么,为什么?





© 2025-05-07 - tinynew.org. All Rights Reserved.
© 2025-05-07 - tinynew.org. 保留所有权利