1. 程式人生 > >【java基礎】java語言的執行緒安全級別

【java基礎】java語言的執行緒安全級別

java是支援多執行緒程式設計的語言,java中提供了很多類,如果把這些類的實現按照執行緒安全級別來排序的話,則由強到弱主要可以分為以下幾個級別

1 絕對執行緒安全

在任何環境下,呼叫者都不需要考慮額外的同步措施,都能夠保證程式的正確性。

這個定義要求很嚴格,java裡面滿足這個要求的類比較少,對於實現jsr133規範(java記憶體模型)的jdk(一般指jdk5.0之上),一般的不變類都是滿足絕地執行緒安全的。比如 String,Integer類。一般情況下,定義瞭如果一個類裡面所有欄位都是final型別的,一般都認為這個類是不變的。不變類都是絕對執行緒安全的。

但是下面這個類的定義,就不是絕對安全的。雖然沒有辦法修改Money類的屬性值(反射機制例外),但是在構造構造Money的時候,可能發生併發問題.這個可以參考

Java記憶體模型-jsr133規範介紹裡面的例子。

public class Money {

private int yuan;

private int fen;

public Money(int yuan, int fen) {

this.yuan = yuan;

this.fen = fen;

}

public String formatString() {

return "" + yuan + "." + fen;

}

}

2 相對執行緒安全

在一般情況下,呼叫者都不需要考慮執行緒同步,大多數情況下,都能夠正常執行。jdk裡面大多數類都是相對安全的。最常見的例子是java裡面Vector類。記得網上經典的面試問題就是Vertor 和 List的區別,一般情況下都會說Vertor是執行緒安全的,List是非執行緒安全的。但是考慮以下情況,一個執行緒遍歷Vector,另外一個執行緒刪除Vector中的一個元素,會導致什麼問題?有可能在read方法中丟擲ArrayIndexOutOfBoundException

import java.util.Vector;

public class VectorTest {

private static Vector v = new Vector();

public static void read() {

int size = v.size();

for (int i = 0; i < size; i++) {

v.get(i);

}

}

public static void delete() {

if (v.iterator().hasNext()) {

v.remove(0);

}

}

}

3 非執行緒安全

在多執行緒環境下,呼叫者需要考慮同步問題。如果呼叫者通過額外的同步機制,可以保證執行緒的安全性。

jdk中,List,Map,DateFormat等物件都是非執行緒安全的。所以在使用這些物件的時候,都要考慮是否會發生執行緒安全問題。

4 執行緒對立

在多執行緒環境中,無論採用什麼樣的機制,都無法解決執行緒安全問題。這種還是極為少見的。比如java.lang.Thread類,提供了suspend,stop,resume方法。

suspend 和 resume 方法可能導致兩個執行緒死鎖。

例如 執行緒A,先鎖住關鍵資源S,然後被執行緒B suspend,由於資源被A鎖住,除非執行緒A被resume,否則其他執行緒無法訪問S,如果遇到S,則阻塞。 而執行緒B suspend執行緒A之後,需要申請關鍵資源S,獲取到S之後,在resume A。此時執行緒A 和 執行緒B就由可能導致死鎖。

對於stop方法,由於呼叫stop方法的時候,被stop的執行緒回釋放所有他獲得的所有monitor,被monitor保護的資源可能存在一致性問題。其他執行緒可能看到的物件就可能不一致。