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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

java并发进程共享变量_JAVA并发编程学习:共享对象

發(fā)布時(shí)間:2025/3/20 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java并发进程共享变量_JAVA并发编程学习:共享对象 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

可見性

在一個(gè)單線程程序中,如果向一個(gè)變量先寫入值,然后在沒有寫干涉的情況下讀取這個(gè)變量,會(huì)得到相同的返回值。但是當(dāng)讀和寫發(fā)生在不同的線程中時(shí),就不能保證讀線程及時(shí)地讀取其他線程寫入的值。在JAVA中所有實(shí)例域、靜態(tài)域和數(shù)組元素存儲(chǔ)在堆內(nèi)存中,堆內(nèi)存在線程之間共享,局部變量,方法定義參數(shù)和異常處理器參數(shù)不會(huì)在線程之間共享,它們不會(huì)有內(nèi)存可見性問題,也不受內(nèi)存模型的影響。為了確保跨線程寫入的內(nèi)存可見性,必須使用同步機(jī)制

下例是主線程和讀線程兩個(gè)線程訪問共享變量ready和number。主線程啟動(dòng)讀線程,然后把number的值設(shè)為42,ready的值賦為true。讀線程進(jìn)行循環(huán),直到發(fā)現(xiàn)ready的值變?yōu)閠rue,然后打印出number的值。雖然看起來會(huì)輸出42,但事實(shí)上,它很有可能打印出0,或者根本不會(huì)終止。這是因?yàn)樗鼪]有使用恰當(dāng)?shù)耐綑C(jī)制,沒能保證主線程寫入ready和number的值對(duì)讀線程是可見的

package com.henrysun.javaSE.bfbc;

/**

* 在沒有同步的情況下共享變量(不要這樣做)

* 重排序現(xiàn)象

* @author Sam Flynn

*

*/

public class GongXiangBianLiangReordering {

private static boolean ready;

private static intnumber;

private static class ReaderThread extends Thread

{

public void run()

{

while(!ready)

{

Thread.yield();

}

System.out.println(number);

}

}

/**

* @param args

*/

public static void main(String[] args) {

new ReaderThread().start();

number=42;

ready=true;

}

}

重排序現(xiàn)象

上面的例子中,可能會(huì)打印0,因?yàn)樵缭趯?duì)number賦值之前,主線程就已經(jīng)寫入ready并使之對(duì)讀線程可見,這叫做“重排序(reordering)”現(xiàn)象。

這里處理器A和處理器B可以同時(shí)把共享變量寫入自己的寫緩沖區(qū)(A1,B1),然后從內(nèi)存中讀取另一個(gè)共享變量(A2,B2),最后才把自己寫緩存區(qū)中保存的臟數(shù)據(jù)刷新到內(nèi)存中(A3,B3)。當(dāng)以這種時(shí)序執(zhí)行時(shí),程序就可以得到x = y = 0的結(jié)果

鎖和可見性

鎖不僅僅是關(guān)于同步互斥的,也是關(guān)于內(nèi)存可見的。當(dāng)線程A執(zhí)行一個(gè)同步塊時(shí),線程B也隨后進(jìn)入了被同一個(gè)鎖監(jiān)視的同步塊中,這時(shí)可以保證,在鎖釋放之前對(duì)A的可見的變量的值,B獲得鎖之后同樣是可見的。換句話說,當(dāng)B執(zhí)行到A相同的鎖監(jiān)視的同步塊時(shí),A在同步塊之中或之前所做的每件事,對(duì)B都是可見的。為了保證所有線程都能夠看到共享的,可變變量的最新值,讀取和寫入線程必須使用公共的鎖進(jìn)行同步

Volatile變量

當(dāng)一個(gè)域聲明為volatile類型后,編譯器與運(yùn)行時(shí)會(huì)監(jiān)視這個(gè)變量:它是共享的,而且對(duì)它的操作不會(huì)與其他的內(nèi)存操作一起被重排序。volatile變量不會(huì)緩存在寄存器或者緩存在其他對(duì)處理器隱藏的地方。所以,讀一個(gè)volatile類型的變量時(shí),總會(huì)返回由某一線程寫入的最新值

但是volatile變量的操作不會(huì)加鎖,也就不會(huì)引起執(zhí)行線程的阻塞,所以它只是輕量級(jí)的同步機(jī)制,正確使用volatile變量的方式包括:用于確保它們所引用的對(duì)象狀態(tài)的可見性,或者用于標(biāo)識(shí)重要的生命周期事件(比如初始化或關(guān)閉)的發(fā)生,即通常被當(dāng)作標(biāo)識(shí)完成、中斷、狀態(tài)的標(biāo)記使用

盡管volatile也可以用來標(biāo)識(shí)其他類型的狀態(tài)信息,但是決定這樣做之前請(qǐng)格外小心。比如,volatile的語(yǔ)義不足以使自增操作(count++)原子化,除非你能保證只有一個(gè)線程對(duì)變量執(zhí)行寫操作。加鎖可以保證可見性與原子性,而volatile變量只能保證可見性

只有滿足了下面的標(biāo)準(zhǔn),才能使用volatile變量

寫入變量時(shí)并不依賴變量的當(dāng)前值;或者能夠確保只有單一的線程修改變量的值

變量不需要與其他的狀態(tài)變量共同參與不變約束

而且,訪問變量時(shí),沒有其他的原因需要加鎖

ThreadLocal

總結(jié)

以上是生活随笔為你收集整理的java并发进程共享变量_JAVA并发编程学习:共享对象的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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