<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Vincent

    Vicent's blog
    隨筆 - 74, 文章 - 0, 評論 - 5, 引用 - 0
    數(shù)據(jù)加載中……

    Java線程安全

    一直不敢寫點什么,是因為戰(zhàn)戰(zhàn)兢兢,生怕寫的不好甚至寫錯了會誤人子弟。隨筆可以隨便寫一下,不用太過計較,可是技術(shù)從來都要不得半點馬虎,差之毫厘,謬以千里啊!但敝帚自珍又不是我的風(fēng)格,雖然文筆不好,也要勉為其難了。廢話少說,進入正題。

    ?

    ?????? 從我開始接觸 Java 的多線程起就總是覺得書上講的不是那么清楚。不是說讀完了不會寫,而是對寫出來的多線程代碼懵懵懂懂,不知道每一句會有什么影響,心里感覺忐忑。后來仔細(xì)研讀 Java 語言規(guī)范后,才慢慢搞明白一些細(xì)節(jié)。我主要想說的,也就是這些經(jīng)驗吧。

    ?

    ?????? 首先要搞清楚的是線程的共享資源,共享資源是多線程中每個線程都要訪問的類變量或?qū)嵗兞浚蚕碣Y源可以是單個類變量或?qū)嵗兞浚部梢允且唤M類變量或?qū)嵗兞俊6嗑€程程序可以有多個共享資源。下面描述他們之間的一對多關(guān)系( * 表示多):

    ??????

    ???????????????????? 多線程程序( 1 ---- 共享資源( * ---- 類變量或?qū)嵗兞浚?/span> 1…*

    ?

    只有類變量和實例變量可以成為共享資源,細(xì)分如下:

    <!--[if !supportLists]-->1.?????? <!--[endif]-->實現(xiàn)線程的類(繼承Thread類、實現(xiàn)Throwable接口的類)的類變量、實例變量。

    <!--[if !supportLists]-->2.?????? <!--[endif]-->實現(xiàn)線程的類的類變量、實例變量的類變量、實例變量,可以不規(guī)范的寫為:TreadClass.ClassOrInstanceVar[.ClassOrInstanceVar]*[]*的內(nèi)容表示無限可重復(fù)。

    <!--[if !supportLists]-->3.?????? <!--[endif]-->不是實現(xiàn)線程的類,但其對象可能是線程的類變量或?qū)嵗兞俊H?/span>ServletEJB。這些類的類變量和實例變量,不規(guī)范的寫為:ServletOrEJB.ClassOrInstanceVar[.ClassOrInstanceVar]*

    <!--[if !supportLists]-->4.?????? <!--[endif]-->特別注意:局部變量、做為參數(shù)傳遞的非類變量、非實例變量不是共享資源。

    ?

    那么什么是線程安全呢?關(guān)于這個問題我在網(wǎng)上百度了一下(沒辦法,有時候 GOOGLE 用不了),發(fā)現(xiàn)不少人在問這個問題,也有不少錯誤的理解。所以我給出一個較容易理解的解釋:在線程中使用共享資源時,能夠保證共享資源在任何時候都是原子的、一致的,這樣的線程就是線程安全的線程。還不太理解?沒有關(guān)系,慢慢解釋。

    ?

    首先來介紹一下共享資源的類型(這是我自己分類的,為了后文好解釋),共享資源從其類型可以分為三類(下文講到變量一律指類變量或?qū)嵗兞浚辉偬貏e指出):

    <!--[if !supportLists]-->1.?????? <!--[endif]-->獨立的基本類型共享資源,如一個簡單的int變量,例:

    public class Cls1 {

    ?????? private int a;

    ?????? public int getA(){return a;}

    ?????? public void setA(int a){this.a = a;}

    }

    可以看到 a 沒有任何依賴。

    public class Cls2{

    ?????? private int a;

    ?????? private int b;

    ?????? private int c;

    ?????? // 沒有對 a 的訪問方法, a Cls 外不可見。

    }

    假設(shè)上面類中 b c 都不依賴 a ,則 a 是這種類型。

    ?

    <!--[if !supportLists]-->2.?????? <!--[endif]-->相互依賴的基本類型共享資源,一個類中的幾個基本類型變量互相依賴,但從對象設(shè)計的角度又不能單獨把這幾個變量設(shè)計成一個類。

    假設(shè)上例 Cls2 中的 b c 互相依賴,則屬此種情況。

    <!--[if !supportLists]-->3.?????? <!--[endif]-->64位的基本類型變量。這個比較特殊,因為某些機器上64變量會分成兩個32位的操作,所以和1不一樣。如doublelong類型。

    <!--[if !supportLists]-->4.?????? <!--[endif]-->類類型的共享資源。如下例中的obj

    public class Cls3{

    ?????? private SomeObj obj;

    }

    public class SomeObj{

    ?????? private int a;

    ?????? private int b;

    }

    ?

    ?????? 其次來看看什么是原子性、一致性。其實在這里我借用了事務(wù) ACID 屬性的 A C ,熟悉的朋友就不用我廢話了。所謂原子性,是指一個共享資源的所有屬性在任何時刻都是一起變化、密不可分的;所謂一致性,是指一個共享資源的所有屬性在變化之后一定會達到一個一致的狀態(tài)。

    ?

    ?????? 最后根據(jù)上述四種共享資源類型,來看看如何做到線程安全。

    ?

    <!--[if !supportLists]-->1.?????? <!--[endif]-->不用做什么,只一個獨立的變量,任何時候它都是原子、一致的。

    <!--[if !supportLists]-->2.?????? <!--[endif]-->使用synchronized關(guān)鍵字,保證幾個變量被一起修改、一起讀取。

    <!--[if !supportLists]-->3.?????? <!--[endif]-->使用volatile關(guān)鍵字,然后就和1一樣了。

    <!--[if !supportLists]-->4.?????? <!--[endif]-->2一樣處理。

    ?

    當(dāng)對訪問共享資源的方法不同時使用 synchronized 關(guān)鍵字時,是什么樣一種情況呢?這是需要特別注意的,這樣不能保證線程安全!看看下面例子的運行結(jié)果就知道了(自己運行啊,我不貼結(jié)果了):

    /**

    ?* $Author: $

    ?* $Date: $

    ?* $Revision: $

    ?* $History: $

    ?*

    ?* Created by feelyou, at time 22:31:53 , 2005-11-16.

    ?*/

    ?

    public class TestThread extends Thread {

    ?

    ? private int a = 0;

    ? private int b = 0;

    ?

    ? public static void main(String[] args) {

    ??? TestThread test = new TestThread();

    ??? for (int i = 0; i < 10; i++) {

    ????? Thread thread = new Thread(test, "thread-" + i);

    ????? thread.start();

    ??? }

    ? }

    ?

    ? public synchronized void doWrite() {

    ??? a++;

    ??? try {

    ????? sleep((int)(Math.random()*100));

    ??? }

    ??? catch (InterruptedException e) {

    ??? }

    ??? b++;

    ??? try {

    ????? sleep((int)(Math.random()*100));

    ??? }

    ??? catch (InterruptedException e) {

    ??? }

    ? }

    ?

    ? public void print() {

    ??? System.out.println("" + Thread.currentThread().getName() + ":a:" + a);

    ??? System.out.println("" + Thread.currentThread().getName() + ":b:" + b);

    ? }

    ?

    ? public void run() {

    ??? super.run();??? //To change body of overridden methods use File | Settings | File Templates.

    ??? for (int i = 0; i < 10; i++) {

    ????? doWrite();

    ????? print();

    ??? }

    ? }

    ?

    ? public synchronized void start() {

    ??? super.start();??? //To change body of overridden methods use File | Settings | File Templates.

    ? }

    }

    ?

    ThreadLocal ThreadLocal 對于線程安全還是很有用的,如果資源不是共享的,那么應(yīng)該使用 ThreadLocal ,但如果確實需要在線程間共享資源, ThreadLocal 就沒有用了!

    ?

    最后,來一個完整的線程安全的例子:

    /**

    ?* $Author: $

    ?* $Date: $

    ?* $Revision: $

    ?* $History: $

    ?*

    ?* Created by feelyou, at time 22:31:53 , 2005-11-16.

    ?*/

    ?

    public class TestThread extends Thread {

    ?

    ? private int a = 0; // 獨立的共享資源

    ? private int b = 0; //b c 互相依賴

    ? private int c = 0;

    ? private volatile long d = 0L; //64

    //? private SomeObj obj = new SomeObj(); // 對象類型,大家自己寫吧,我就不寫了。

    ?

    ? public static void main(String[] args) {

    ??? TestThread test = new TestThread();

    ??? for (int i = 0; i < 10; i++) {

    ????? Thread thread = new Thread(test, "thread-" + i);

    ????? thread.start();

    ??? }

    ? }

    ?

    ? public synchronized void doWrite() {

    ??? b++;

    ??? try {

    ????? sleep((int)(Math.random()*100));

    ??? }

    ??? catch (InterruptedException e) {

    ??? }

    ??? c++;

    ??? try {

    ?? ???sleep((int)(Math.random()*100));

    ??? }

    ??? catch (InterruptedException e) {

    ??? }

    ? }

    ?

    ? public synchronized void print() {

    ??? System.out.println("" + Thread.currentThread().getName() + ":b:" + b);

    ??? System.out.println("" + Thread.currentThread().getName() + ":c:" + c);

    ? }

    ?

    ? private void setA(int a) {

    ? ??? this.a = a;

    ? }

    ?

    ? private int getA() {

    ? ??? return a;

    ? }

    ?

    ? public long getD() {

    ? ??? return d;

    ? }

    ?

    ? public void setD(long d) {

    ? ??? this.d = d;

    ? }

    ?

    ? public void run() {

    ??? super.run();??? //To change body of overridden methods use File | Settings | File Templates.

    ??? for (int i = 0; i < 10; i++) {

    ????? doWrite();

    ????? print();

    ????? setA(i);

    ????? System.out.println(getA());

    ????? setD(18456187413L * i);

    ????? System.out.println(getD());

    ??? }

    ? }

    ?

    ? public synchronized void start() {

    ??? super.start();??? //To change body of overridden methods use File | Settings | File Templates.

    ? }

    }

    posted on 2006-08-24 15:42 Binary 閱讀(429) 評論(0)  編輯  收藏 所屬分類: j2se

    主站蜘蛛池模板: 亚洲人成图片小说网站| 亚洲成a人片毛片在线| 亚洲欧美日韩综合久久久| aⅴ在线免费观看| 成人国产mv免费视频| 亚洲综合小说另类图片动图| 在线观看免费视频一区| 一本色道久久综合亚洲精品| 中文在线免费视频| 久久综合九九亚洲一区| 2019中文字幕在线电影免费| 亚洲av成人综合网| 天天看片天天爽_免费播放| 午夜亚洲WWW湿好爽| 精品女同一区二区三区免费站| 久久亚洲sm情趣捆绑调教 | 亚洲天堂视频在线观看| 久久久久久国产精品免费免费男同| 久久久久亚洲AV无码专区首| 蜜臀98精品国产免费观看| 亚洲最大成人网色香蕉| 免费看美女被靠到爽| 久久久久亚洲AV无码永不| 2015日韩永久免费视频播放| 亚洲最大av资源站无码av网址| 无码国产亚洲日韩国精品视频一区二区三区| 免费一级全黄少妇性色生活片| 亚洲熟妇av一区二区三区 | 免费看又爽又黄禁片视频1000| 青青青亚洲精品国产| 中文国产成人精品久久亚洲精品AⅤ无码精品| 最近免费中文字幕中文高清| 亚洲成人福利网站| 成年女人永久免费观看片| 国产做国产爱免费视频| 亚洲不卡1卡2卡三卡2021麻豆| 免费成人在线观看| 在线成人爽a毛片免费软件| 亚洲aⅴ无码专区在线观看春色| 亚洲精品字幕在线观看| eeuss免费影院|