• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            woaidongmao

            文章均收錄自他人博客,但不喜標題前加-[轉貼],因其丑陋,見諒!~
            隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
            數據加載中……

            java 線程安全

            四種方式    sychronized關鍵字

            1. sychronized method(){}
            2. sychronized (objectReference) {/*block*/}
            3. static synchronized method(){}
            4. sychronized(classname.class)

            其中12是代表鎖當前對象,即一個對象就一個鎖34代表鎖這個類,即這個類的鎖
            要注意的是sychronized method()不是鎖這個函數,而是鎖對象,即:如果這個類中有兩個方法都是sychronized,那么只要有兩個線程共享一個該類的reference,每個調用這兩個方法之一,不管是否同一個方法,都會用這個對象鎖進行同步。鎖34類推,即該類的不同reference調用了sychronized區段的咚咚就會受類鎖的控制

            還有,如果兩個函數調用的先后順序不能被打斷,那么可以有個專門的鎖對象來完成這個任務:
            class MyLock
            {
                  synchronized getLock()
                  {
                      //####
            還沒寫完
                  }
            }

            五個等級   參見effective java  Item 52 Document thread safety

            1. immutable   不可變對象
            2. thread-safe 線程安全的,可以放心使用,如java.util.Timer
            3. conditionally thread-safe 條件線程安全的,如VectorHashtable,一般是安全的,除非存在幾個方法調用之間的順序不能被打斷,這時可以用額外的鎖來完成
            4. thread-compatible 可以使用synchronized objectReference)來協助完成對線程的調用
            5. thread-hostile 不安全的

            wait & notifyAll

            在循環中使用wait 使用notifyAll而不是notify

            pipe

            java中也有pipe的,四個類:PipedInputStream, PipedInputReader, PipedOutputStream, PipedOutputWriter 下面是一段生產者消費者的代碼(摘自core javaII):

                /* set up pipes */
                PipedOutputStream pout1 = new PipedOutputStream();
                PipedInputStream pin1 = new PipedInputStream(pout1);
                PipedOutputStream pout2 = new PipedOutputStream();
                PipedInputStream pin2 = new PipedInputStream(pout2);
                /* construct threads */
                Producer prod = new Producer(pout1);
                Filter filt = new Filter(pin1, pout2);
                Consumer cons = new Consumer(pin2);
                /* start threads */
                prod.start(); filt.start(); cons.start();

            注意

            long double是簡單類型中兩個特殊的咚咚:java讀他們要讀兩次,所以需要同步
            死鎖是一個經典的多線程問題,因為不同的線程都在等待那些根本不可能被釋放的鎖,從而導致所有的工作都無法完成。假設有兩個線程,分別代表兩個饑餓的人,他們必須共享刀叉并輪流吃飯。他們都需要獲得兩個鎖:共享刀和共享叉的鎖。假如線程 "A" 獲得了刀,而線程 "B" 獲得了叉。線程 A 就會進入阻塞狀態來等待獲得叉,而線程 B 則阻塞來等待 A 所擁有的刀。這只是人為設計的例子,但盡管在運行時很難探測到,這類情況卻時常發生。雖然要探測或推敲各種情況是非常困難的,但只要按照下面幾條規則去設計系統,就能夠避免死鎖問題:

            ·   讓所有的線程按照同樣的順序獲得一組鎖。這種方法消除了 X Y 的擁有者分別等待對方的資源的問題。

            ·    

            ·   將多個鎖組成一組并放到同一個鎖下。前面死鎖的例子中,可以創建一個銀器對象的鎖。于是在獲得刀或叉之前都必須獲得這個銀器的鎖。

            ·    

            ·   將那些不會阻塞的可獲得資源用變量標志出來。當某個線程獲得銀器對象的鎖時,就可以通過檢查變量來判斷是否整個銀器集合中的對象鎖都可獲得。如果是,它就可以獲得相關的鎖,否則,就要釋放掉銀器這個鎖并稍后再嘗試。

            ·    

            ·   最重要的是,在編寫代碼前認真仔細地設計整個系統。多線程是困難的,在開始編程之前詳細設計系統能夠幫助你避免難以發現死鎖的問題。

            Volatile 變量. volatile 關鍵字是 Java 語言為優化編譯器設計的。以下面的代碼為例:

            class VolatileTest {

             

               public void foo() {

                  boolean flag = false;

             

                  if(flag) {

                     //this could happen

                  }

               }

            }

             

            一個優化的編譯器可能會判斷出 if 部分的語句永遠不會被執行,就根本不會編譯這部分的代碼。如果這個類被多線程訪問, flag 被前面某個線程設置之后,在它被 if 語句測試之前,可以被其他線程重新設置。用 volatile 關鍵字來聲明變量,就可以告訴編譯器在編譯的時候,不需要通過預測變量值來優化這部分的代碼。

             

            無法訪問的線程 有時候雖然獲取對象鎖沒有問題,線程依然有可能進入阻塞狀態。在 Java 編程中 IO 就是這類問題最好的例子。當線程因為對象內的 IO 調用而阻塞時,此對象應當仍能被其他線程訪問。該對象通常有責任取消這個阻塞的 IO 操作。造成阻塞調用的線程常常會令同步任務失敗。如果該對象的其他方法也是同步的,當線程被阻塞時,此對象也就相當于被冷凍住了。其他的線程由于不能獲得對象的鎖,就不能給此對象發消息(例如,取消 IO 操作)。必須確保不在同步代碼中包含那些阻塞調用,或確認在一個用同步阻塞代碼的對象中存在非同步方法。盡管這種方法需要花費一些注意力來保證結果代碼安全運行,但它允許在擁有對象的線程發生阻塞后,該對象仍能夠響應其他線程。

            調用
            yield() 方法能夠將當前的線程從處理器中移出到準備就緒隊列中。另一個方法則是調用 sleep() 方法,使線程放棄處理器,并且在 sleep 方法中指定的時間間隔內睡眠。

            正如你所想的那樣,將這些方法隨意放在代碼的某個地方,并不能夠保證正常工作。如果線程正擁有一個鎖(因為它在一個同步方法或代碼塊中),則當它調用 yield() 時不能夠釋放這個鎖。這就意味著即使這個線程已經被掛起,等待這個鎖釋放的其他線程依然不能繼續運行。為了緩解這個問題,最好不在同步方法中調用 yield 方法。將那些需要同步的代碼包在一個同步塊中,里面不含有非同步的方法,并且在這些同步代碼塊之外才調用 yield

            另外一個解決方法則是調用 wait() 方法,使處理器放棄它當前擁有的對象的鎖。如果對象在方法級別上使同步的,這種方法能夠很好的工作。因為它僅僅使用了一個鎖。如果它使用 fine-grained 鎖,則 wait() 將無法放棄這些鎖。此外,一個因為調用 wait() 方法而阻塞的線程,只有當其他線程調用 notifyAll() 時才會被喚醒。

            在進行多線程編程時,經常要使用同步互斥機構,但java本身沒有提供的同步互斥機構,僅提供了兩個與同步互斥有關的方法:wait()notify(),可以用來設計信號量類:mySemaphore,它是按照Dijkstra提出的計數信號量的思想設計的。

            mySemaphore
            有兩個最重要的成員方法:P()V()。這兩個方法實際就實現了信號量的P操作和V操作。具體描述如下:

            public synchronized void P(){

            semaphore--;

            if(semaphore<0){

            try{

            wait();

            }catch(InterruptedException ie){}

            }

            }

            public synchronized void V(){

            semaphore++;

            if(semaphore<=0)

            notify();

            }

            其中,semaphore變量記錄了信號量的狀態,wait()方法相當于block原語,用于阻塞線程的執行,notify()方法相當于wakeup原語,用于喚醒線程恢復運行。由于這兩個方法定義為synchronized,這樣java虛擬機可保證這兩個方法的原子執行,從而實現了PV操作。

            二、管道

            并發程序的多個線程之間的通訊通常是使用管道進行,jdk提供了兩個管道類:PipedInpuStreamPipedOutputStream,前者用于輸入,后者用于輸出。這兩種管道應該是能夠多次連接和關閉,在實現過程中,卻發現它們在關閉后,不能重新建立連接。經過仔細調試后,發現jdk的源代碼在處理關閉時釋放資源存在著缺陷,因此需要編寫自己的管道類:MyPipedInputStreamMyPipedOutputStream。這兩個類直接從InputStreamOutputStream繼承而來,其成員方法與實現基本與PipedInputStreamPipedOutputStream一致,只是在處理關閉時,將類中的成員變量的值恢復成未連接時的初始值。另外,原有的管道了提供的管道容量只有1024個字節,在傳輸數據量較大時,可能會發生溢出,而在自己的管道類中可以任意設置管道容量,例如可以根據需要把管道容量設為64KB。以下僅給出了相應的關閉例程:

            1
            MyPipedInputStream

            public void close() throws IOException {

            in = -1;

            out = 0;

            closedByReader = true;

            connected = false;

            closed = true;

            buffer = new byte[PIPE_SIZE];

            }

            2
            MyPipedOutputStream

            public void close() throws IOException {

            if (sink != null) {

            sink.receivedLast();

            sink.closed = true;

            }

            sink = null;

            connected = false;

            }

             

            posted on 2009-08-25 22:44 肥仔 閱讀(367) 評論(0)  編輯 收藏 引用 所屬分類: Web-后臺

            亚洲色婷婷综合久久| 午夜福利91久久福利| 人妻无码久久一区二区三区免费 | 天天躁日日躁狠狠久久| 99久久精品国产麻豆| 久久久久久综合一区中文字幕 | 亚洲国产精品成人久久蜜臀| 噜噜噜色噜噜噜久久| 国产成人久久精品激情 | 无码国内精品久久人妻| 久久久久国产精品| 久久九九久精品国产免费直播| 人妻精品久久无码专区精东影业| 国产精品免费久久| 久久亚洲私人国产精品vA| 久久综合精品国产一区二区三区| 麻豆AV一区二区三区久久| 日韩十八禁一区二区久久| 91精品国产91久久久久福利| 亚洲综合久久久| 久久91这里精品国产2020| AAA级久久久精品无码片| 四虎国产精品免费久久| 9999国产精品欧美久久久久久| 伊人久久成人成综合网222| 大伊人青草狠狠久久| 久久亚洲春色中文字幕久久久| 亚洲人AV永久一区二区三区久久 | 久久精品国产福利国产琪琪| 久久国产免费观看精品| 色综合久久久久久久久五月| 久久这里都是精品| 伊人色综合久久天天人守人婷 | 久久A级毛片免费观看| 久久婷婷五月综合成人D啪| 久久嫩草影院免费看夜色| 99久久精品国产一区二区| 久久精品9988| 久久成人精品| 一本久久免费视频| 亚洲伊人久久精品影院|