日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java内存模型和优化

發(fā)布時(shí)間:2023/12/3 java 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java内存模型和优化 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

總覽

許多多線程代碼開發(fā)人員都熟悉這樣的想法,即不同的線程可以對(duì)持有的值有不同的看法,這不是唯一的原因,即如果線程不安全,它可能不會(huì)看到更改。 JIT本身可以發(fā)揮作用。

為什么不同的線程看到不同的值?

當(dāng)您有多個(gè)線程時(shí),它們將嘗試?yán)缤ㄟ^嘗試訪問同一內(nèi)存來最小化它們將交互的數(shù)量。 為此,他們有一個(gè)單獨(dú)的
本地副本,例如在1級(jí)緩存中。 該緩存通常最終是一致的。 我看到兩個(gè)線程看到不同值的短時(shí)間介于一微秒到十毫秒之間。 最終,線程被上下文切換,緩存被清除或更新。 無法保證何時(shí)會(huì)發(fā)生這種情況,但幾乎總是不到一秒鐘。

JIT如何發(fā)揮作用?

Java內(nèi)存模型說,不能保證不是線程安全的字段將看到更新。 這允許JIT進(jìn)行優(yōu)化,將僅讀取而不寫入的值有效地內(nèi)聯(lián)到代碼中。 這意味著即使更新了緩存,更改也可能不會(huì)反映在代碼中。

一個(gè)例子

該代碼將一直運(yùn)行,直到將布爾值設(shè)置為false為止。

>static class MyTask implements Runnable {private final int loopTimes;private boolean running = true;boolean stopped = false;public MyTask(int loopTimes) {this.loopTimes = loopTimes;}@Overridepublic void run() {try {while (running) {longCalculation();}} finally {stopped = true;}}private void longCalculation() {for (int i = 1; i < loopTimes; i++)if (Math.log10(i) < 0)throw new AssertionError();} }public static void main(String... args) throws InterruptedException {int loopTimes = Integer.parseInt(args[0]);MyTask task = new MyTask(loopTimes);Thread thread = new Thread(task);thread.setDaemon(true);thread.start();TimeUnit.MILLISECONDS.sleep(100);task.running = false;for (int i = 0; i < 200; i++) {TimeUnit.MILLISECONDS.sleep(500);System.out.println("stopped = " + task.stopped);if (task.stopped)break;} }

此代碼反復(fù)執(zhí)行一些對(duì)內(nèi)存沒有影響的工作。 它唯一的區(qū)別是需要多長(zhǎng)時(shí)間。 通過花費(fèi)更長(zhǎng)的時(shí)間,它將確定在運(yùn)行之前或之后將run()中的代碼優(yōu)化為false。

如果我使用10或100和-XX:+ PrintCompilation運(yùn)行此命令,則會(huì)看到

111 1 java.lang.String::hashCode (55 bytes) 112 2 java.lang.String::charAt (29 bytes) 135 3 vanilla.java.perfeg.threads.OptimisationMain$MyTask :longCalculation (35 bytes) 204 1 % ! vanilla.java.perfeg.threads.OptimisationMain$MyTask :run @ 0 (31 bytes) stopped = false stopped = false stopped = false stopped = false ... many deleted ... stopped = false stopped = false stopped = false stopped = false stopped = false

如果我用1000運(yùn)行它,您會(huì)看到run()尚未編譯并且線程停止

112 1 java.lang.String::hashCode (55 bytes) 112 2 java.lang.String::charAt (29 bytes) 133 3 vanilla.java.perfeg.threads.OptimisationMain $MyTask::longCalculation (35 bytes) 135 1 % vanilla.java.perfeg.threads.OptimisationMain $MyTask::longCalculation @ 2 (35 bytes) stopped = true

一旦線程被編譯,即使線程將進(jìn)行多次上下文切換等,更改也永遠(yuǎn)不會(huì)被看到。

如何解決這個(gè)問題

簡(jiǎn)單的解決方案是使該字段易變。 這將確保該字段的值是一致的,而不僅僅是最終一致的,這就是緩存可能為您執(zhí)行的操作。

結(jié)論

雖然有許多類似的問題示例; 為什么我的線程沒有停止? 答案更多與Java內(nèi)存模型有關(guān),Java內(nèi)存模型允許JIT“內(nèi)聯(lián)”它執(zhí)行硬件的字段,并在不同的緩存中具有多個(gè)數(shù)據(jù)副本。

參考: Vanilla Java博客上的JCG合作伙伴 Peter Lawrey提供的Java內(nèi)存模型和優(yōu)化 。

翻譯自: https://www.javacodegeeks.com/2013/01/java-memory-model-and-optimisation-2.html

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的Java内存模型和优化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。