java并發的處理方式.doc_第1頁
java并發的處理方式.doc_第2頁
java并發的處理方式.doc_第3頁
java并發的處理方式.doc_第4頁
java并發的處理方式.doc_第5頁
已閱讀5頁,還剩8頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、java 并發的處理方式1 什么是并發問題。 多個進程或線程同時(或著說在同一段時間內 )訪問同一資源會產生并發問題。銀行兩操作員同時操作同一賬戶就是典型的例子。比如 A、 B 操作員同時讀取一余額為 1000 元的賬戶, A 操作員為該賬戶增加 100 元,B 操作員同時為該賬戶減去50 元,A先提交,B后提交。 最后實際賬戶余額為1000-50=950元,但本該為1000+100-50=1050。這就是典型的并發問題。如何解決?可以用鎖。用法1public class Testpublic synchronized void print().;某線程執行print() 方法,則該對象將加鎖

2、。其它線程將無法執行該對象的所有synchronized塊。用法2public classTestpublic void print()synchronized(this)/鎖住本對象.;同用法 1, 但更能體現synchronized用法的本質。用法3public class Testprivate String a = test;public void print()synchronized(a)/鎖住 a 對象.;public synchronized void t().; / 這個同步代碼塊不會因為print()而鎖定.執行 print() ,會給對象 a 加鎖,注意不是給Test 的

3、對象加鎖,也就是說Test 對象的其它synchronized方法不會因為print() 而被鎖。同步代碼塊執行完,則釋放對a 的鎖。為了鎖住一個對象的代碼塊而不影響該對象其它synchronized塊的高性能寫法:public class Testprivate byte lock = new byte0;public void print()synchronized(lock).;public synchronized void t().;靜態方法的鎖public class Testpublic synchronized static void execute().;效果同 public

4、 class Testpublic static void execute()synchronized(TestThread.class).;3 Java 中的鎖與排隊上廁所。鎖就是阻止其它進程或線程進行資源訪問的一種方式,即鎖住的資源不能被其它請求訪問。在 JAVA 中,sychronized關鍵字用來對一個對象加鎖。比如 :public class MyStack int idx = 0;char data = new char6;public synchronizedvoid push(char c) dataidx = c;idx+;public synchronized char p

5、op() idx-;return dataidx;public static void main(String args) MyStack m = new MyStack();/*下面對象 m 被加鎖。 嚴格的說是對象m 的所有synchronized無法執行 m塊被加鎖。如果存在另一個試圖訪問對象的 push 和pop 方法。m 的線程T,那么T*/m.pop();/ 對象 m 被加鎖。Java 的加鎖解鎖跟多個人排隊等一個公共廁位完全一樣。第一個人進去后順手把門從里面鎖住,其它人只好排隊等。第一個人結束后出來時,門才會打開(解鎖)。輪到第二個人進去,同樣他又會把門從里面鎖住,其它人繼續排隊

6、等待。用廁所理論可以很容易明白: 一個人進了一個廁位,這個廁位就會鎖住,但不會導致另一個廁位也被鎖住,因為一個人不能同時蹲在兩個廁位里。對于 Java就是說: Java 中的鎖是針對同一個對象的,不是針對class 的。看下例: MyStatckm1 = new MyStack();MyStatck m2 = new Mystatck();m1.pop();m2.pop();m1 對象的鎖是不會影響 m2 的鎖的,因為它們不是同一個廁位。就是說,假設有 3 線程 t1,t2,t3 操作 m1 ,那么這 3 個線程只可能在 m1 上排隊等,假設另 2 個線程 t8,t9 在操作 m2 ,那么 t

7、8,t9 只會在 m2 上等待。而 t2 和 t8 則沒有關系,即使 m2 上的鎖釋放了, t1,t2,t3 可能仍要在 m1 上排隊。原因無它, 不是同一個廁位耳。 Java 不能同時對一個代碼塊加兩個鎖,這和數據庫鎖機制不同,數據庫可以對一條記錄同時加好幾種不同的鎖,請參見:6b151b9a3.html4 何時釋放鎖?一般是執行完畢同步代碼塊(鎖住的代碼塊)后就釋放鎖,也可以用wait() 方式半路上釋放鎖。wait() 方式就好比蹲廁所到一半,突然發現下水道堵住了,不得已必須出來站在一邊, 好讓修下水道師傅(準備執行 notify 的一個線程)進去疏通馬桶,疏通完畢,師傅大喊一聲: 已經

8、修好了(notify) ,剛才出來的同志聽到后就重新排隊。注意啊, 必須等師傅出來啊,師傅不出來,誰也進不去。也就是說notify后,不是其它線程馬上可以進入封鎖區域活動了,而是必須還要等 notify 代碼所在的封鎖區域執行完畢從而釋放鎖以后,其它線程才可進入。這里是wait 與 notify 代碼示例: publicsynchronized char pop() char c;while (buffer.size() = 0) try this.wait(); / 從廁位里出來 catch (InterruptedException e) / ignore it.c = (Characte

9、r)buffer.remove(buffer.size()-1).charValue();return c;public synchronized void push(char c) this.notify(); / 通知那些wait() 的線程重新排隊。注意:僅僅是通知它們重新排隊。Character charObj = new Character(c);buffer.addElement(charObj);/ 執行完畢,釋放鎖。那些排隊的線程就可以進來了。再深入一些。 由于 wait() 操作而半路出來的同志沒收到notify信號前是不會再排隊的, 他會在旁邊看著這些排隊的人(其中修水管師

10、傅也在其中) 。注意,修水管的師傅不能插隊,也得跟那些上廁所的人一樣排隊,不是說一個人蹲了一半出來后,修水管師傅就可以突然冒出來然后立刻進去搶修了,他要和原來排隊的那幫人公平競爭,因為他也是個普通線程。如果修水管師傅排在后面,則前面的人進去后,發現堵了,就 wait ,然后出來站到一邊,再進去一個,再 wait ,出來,站到一邊, 只到師傅進去執行 notify. 這樣,一會兒功夫, 排隊的旁邊就站了一堆人,等著 notify. 終于,師傅進去,然后 notify 了,接下來呢? 1. 有一個 wait 的人(線程)被通知到。2. 為什么被通知到的是他而不是另外一個wait 的人?取決于 JV

11、M. 我們無法預先判斷出哪一個會被通知到。也就是說,優先級高的不一定被優先喚醒,等待時間長的也不一定被優先喚醒,一切不可預知!(當然,如果你了解該JVM 的實現,則可以預知) 。3. 他(被通知到的線程)要重新排隊。4. 他會排在隊伍的第一個位置嗎?回答是: 不一定。他會排最后嗎?也不一定。但如果該線程優先級設的比較高,那么他排在前面的概率就比較大。5. 輪到他重新進入廁位時,他會從上次wait() 的地方接著執行,不會重新執行。惡心點說就是,他會接著拉巴巴,不會重新拉。6. 如果師傅 notifyAll(). 則那一堆半途而廢出來的人全部重新排隊。順序不可知。Java DOC上說, The

12、awakened threads will not be able toproceed until the current thread relinquishes the lock onthis object( 當前線程釋放鎖前,喚醒的線程不能去執行) 。這用廁位理論解釋就是顯而易見的事。5 Lock的使用用synchronized關鍵字可以對資源加鎖。用Lock關鍵字也可以。它是 JDK1.5 中新增內容。用法如下:classBoundedBuffer final Lock lock = new ReentrantLock();final Condition notFull= lock.ne

13、wCondition();final Condition notEmpty = lock.newCondition();final Object items = new Object100;int putptr, takeptr, count;public void put(Object x)throws InterruptedException lock.lock();try while (count = items.length)notFull.await();itemsputptr = x;if (+putptr = items.length) putptr = 0;+count;not

14、Empty.signal(); finally lock.unlock();public Object take() throws InterruptedExceptionlock.lock();try while (count = 0)notEmpty.await();Object x = itemstakeptr;if (+takeptr = items.length) takeptr = 0;-count;notFull.signal();return x; finally lock.unlock();(注:這是 JavaDoc里的例子,是一個阻塞隊列的實現例子。所謂阻塞隊列,就是一個隊

15、列如果滿了或者空了,都會導致線程阻塞等待。 Java 里的ArrayBlockingQueue提供了現成的阻塞隊列,不需要自己專門再寫一個了。)一個對象的lock.lock() 和 lock.unlock() 之間的代碼將會被鎖住。 這種方式比起 synchronize 好在什么地方?簡而言之, 就是對 wait 的線程進行了分類。用廁位理論來描述,則是那些蹲了一半而從廁位里出來等待的人原因可能不一樣,有的是因為馬桶堵了,有的是因為馬桶沒水了。通知 (notify) 的時候,就可以喊:因為馬桶堵了而等待的過來重新排隊(比如馬桶堵塞問題被解決了),或者喊,因為馬桶沒水而等待的過來重新排隊 (比如馬桶沒水問題被解決了)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論