Java線程并發(fā)訪問(wèn)代碼分析
這篇文章主要介紹了Java線程并發(fā)訪問(wèn)代碼分析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
class ConcurrentThread {
/**
* 分析線程并發(fā)訪問(wèn)代碼解釋原因
* volatile關(guān)鍵字:
* 1):保證了不同線程對(duì)這個(gè)變量進(jìn)行操作時(shí)的可見(jiàn)性,即一個(gè)線程修改了某個(gè)變量的值,這新值對(duì)其他線程來(lái)說(shuō)是立即可見(jiàn)的
* 2):禁止進(jìn)行指令重排序
* volatile本質(zhì)是告訴JVM當(dāng)前變量在寄存器(工作內(nèi)存)中的值是不確定的,需要從主存中讀取
*/
private volatile int count = 0;
public void inc() {
try {
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
}
@Override
public String toString() {
return "[count=" + count + "]";
}
}
//----------------------------------------
public class VolatileTest {
public static void main(String[] args) {
final ConcurrentThread counter = new ConcurrentThread();
for (int i = 0; i < 1000; i++) {
new Thread(new Runnable() {
@Override
public void run() {
counter.inc();
}
}).start();
}
System.out.println(counter);
}
}

原因解釋:在Java的內(nèi)存模型中每一個(gè)線程運(yùn)行時(shí)都有一個(gè)線程棧,線程棧保存了線程運(yùn)行時(shí)候變量值信息
當(dāng)線程訪問(wèn)某一個(gè)對(duì)象值得時(shí)候:
1、通過(guò)對(duì)象的引用找到對(duì)應(yīng)在堆內(nèi)存的變量的值
2、把堆內(nèi)存變量的具體值load到線程本地內(nèi)存中,建立了一個(gè)變量副本,之后線程就不再和對(duì)象在堆內(nèi)存變量值有任何關(guān)系,而是直接修改副本變量的值,在修改完之后的某一個(gè)時(shí)刻(線程退出之前),自動(dòng)把線程變量副本的值回寫到對(duì)象在堆中變量。這樣堆中的對(duì)象的值就產(chǎn)生變化了。
結(jié)合上例,也就是說(shuō)上面主函數(shù)中開(kāi)啟了1000個(gè)子線程,每個(gè)線程都有一個(gè)變量副本,每個(gè)線程修改變量只是臨時(shí)修改了自己的副本,當(dāng)線程結(jié)束時(shí)再將修改的值寫入在主內(nèi)存中,這樣就出現(xiàn)了線程安全問(wèn)題(拿到了主內(nèi)存中過(guò)時(shí)的變量值),因此結(jié)果就不可能等于1000了,一般都會(huì)小于1000.

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
java 中 System.out.println()和System.out.write()的區(qū)別
這篇文章主要介紹了 java 中 System.out.println()和System.out.write()的區(qū)別.的相關(guān)資料,需要的朋友可以參考下2017-04-04
深入理解Java中沒(méi)那么簡(jiǎn)單的單例模式
這篇文章主要給大家詳細(xì)介紹了Java單例模式,關(guān)于Java中的單例模式并非看起來(lái)那么簡(jiǎn)單的,為什么要這么說(shuō)呢?下面通過(guò)這篇文章來(lái)一起看看吧,有需要的朋友們可以參考借鑒。2017-01-01
Java分頁(yè)簡(jiǎn)介_(kāi)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了Java分頁(yè)簡(jiǎn)介的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
詳解SpringBoot如何自定義一個(gè)Starter
小伙伴們?cè)?jīng)可能都經(jīng)歷過(guò)整天寫著CURD的業(yè)務(wù),都沒(méi)寫過(guò)一些組件相關(guān)的東西,這篇文章記錄一下SpringBoot如何自定義一個(gè)Starter。原理和理論就不用多說(shuō)了,可以在網(wǎng)上找到很多關(guān)于該方面的資料,這里主要分享如何自定義2022-11-11
SpringBoot內(nèi)置tomcat啟動(dòng)原理詳解
這篇文章主要介紹了SpringBoot內(nèi)置tomcat啟動(dòng)原理詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
SpringBoot接入deepseek深度求索示例代碼(jdk1.8)
這篇文章主要介紹了SpringBoot接入deepseek深度求索的相關(guān)資料,包括建API?key、封裝詢問(wèn)Deepseek的工具方法(在配置文件中添加key值)、調(diào)用測(cè)試并確保端口一致例如8091,最后運(yùn)行結(jié)果,需要的朋友可以參考下2025-02-02

