多執行緒之間的競爭
進行多執行緒程式設計,同步控制是非常重要的,而同步控制就涉及到了鎖。
對程式碼進行同步控制我們可以選擇同步方法,也可以選擇同步塊,這兩種方式各有優缺點,至於具體選擇什麼方式,就見仁見智了,同步塊不僅可以更加精確的控制物件鎖,也就是控制鎖的作用域,何謂鎖的作用域?鎖的作用域就是從鎖被獲取到其被釋放的時間。而且可以選擇要獲取哪個物件的物件鎖。但是如果在使用同步塊機制時,如果使用過多的鎖也會容易引起死鎖問題,同時獲取和釋放所也有代價,而同步方法,它們所擁有的鎖就是該方法所屬的類的物件鎖,換句話說,也就是this物件,而且鎖的作用域也是整個方法,這可能導致其鎖的作用域可能太大,也有可能引起死鎖,同時因為可能包含了不需要進行同步的程式碼塊在內,也會降低程式的執行效率。而不管是同步方法還是同步塊,我們都不應該在他們的程式碼塊內包含無限迴圈,如果程式碼內部要是有了無限迴圈,那麼這個同步方法或者同步塊在獲取鎖以後因為程式碼會一直不停的迴圈著執行下去,也就沒有機會釋放它所獲取的鎖,而其它等待這把鎖的執行緒就永遠無法獲取這把鎖,這就造成了一種死鎖現象。
詳細解說一下同步方法的鎖,同步方法分為靜態同步方法與非靜態同步方法。
所有的非靜態同步方法用的都是同一把鎖——例項物件本身,也就是說如果一個例項物件的非靜態同步方法獲取鎖後,該例項物件的其他非靜態同步方法必須等待獲取鎖的方法釋放鎖後才能獲取鎖,可是別的例項物件的非靜態同步方法因為跟該例項物件的非靜態同步方法用的是不同的鎖,所以毋須等待該例項物件已獲取鎖的非靜態同步方法釋放鎖就可以獲取他們自己的鎖。
而所有的靜態同步方法用的也是同一把鎖——類物件本身,這兩把鎖是兩個不同的物件,所以靜態同步方法與非靜態同步方法之間是不會有競態條件的。但是一旦一個靜態同步方法獲取鎖後,其他的靜態同步方法都必須等待該方法釋放鎖後才能獲取鎖,而不管是同一個例項物件的靜態同步方法之間,還是不同的例項物件的靜態同步方法之間,只要它們同一個類的例項物件!
總之,對與同一個例項的非靜態同步方法只對非靜態方法有效,靜態同步方法只對靜態同步方法有效,靜態同步方法和非靜態同步方法是互不干擾的。
而對於同步塊,由於其鎖是可以選擇的,所以只有使用同一把鎖的同步塊之間才有著競態條件,這就得具體情況具體分析了,但這裡有個需要注意的地方,同步塊的鎖是可以選擇的,但是不是可以任意選擇的!!!!這裡必須要注意一個物理物件和一個引用物件的例項變數之間的區別!使用一個引用物件的例項變數作為鎖並不是一個好的選擇,因為同步塊在執行過程中可能會改變它的值,其中就包括將其設定為null,而對一個null物件加鎖會產生異常,並且對不同的物件加鎖也違背了同步的初衷!這看起來是很清楚的,但是一個經常發生的錯誤就是選用了錯誤的鎖物件,因此必須注意:同步是基於實際物件而不是物件引用的!多個變數可以引用同一個物件,變數也可以改變其值從而指向其他的物件,因此,當選擇一個物件鎖時,我們要根據實際物件而不是其引用來考慮!作為一個原則,不要選擇一個可能會在鎖的作用域中改變值的例項變數作為鎖物件!!!!
Java執行緒:執行緒的同步與鎖
private int x = 100;
public int getX() {
return x;
}
public int fix(int y) {
x = x - y;
return x;
}
}
private Foo foo = new Foo();
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
Thread ta = new Thread(r, "Thread-A");
Thread tb = new Thread(r, "Thread-B");
ta.start();
tb.start();
}
public void run() {
for (int i = 0; i < 3; i++) {
this.fix(30);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " : 當前foo物件的x值= " + foo.getX());
}
}
public int fix(int y) {
return foo.fix(y);
}
}
Thread-B : 當前foo物件的x值= 40
Thread-B : 當前foo物件的x值= -20
Thread-A : 當前foo物件的x值= -50
Thread-A : 當前foo物件的x值= -80
Thread-B : 當前foo物件的x值= -80
Process finished with exit code 0
6)、執行緒睡眠時,它所持的任何鎖都不會釋放。
synchronized (this) {
x = x - y;
}
return x;
}
return x++;
}
synchronized (this) {
return x;
}
}
public static int setName(String name){
synchronized(Xxx.class){
Xxx.name = name;
}
}
相關文章
- 解決多執行緒競爭條件——臨界區執行緒
- 多執行緒之間的通訊執行緒
- 多執行緒下解決資源競爭的7種方法執行緒
- 多執行緒之間通訊及執行緒池執行緒
- 手撕Java多執行緒(四)執行緒之間的協作Java執行緒
- 多執行緒-執行緒控制之休眠執行緒執行緒
- 多執行緒-執行緒控制之加入執行緒執行緒
- 多執行緒-執行緒控制之禮讓執行緒執行緒
- netty Recycler(三) 多執行緒回收物件時競爭機制的解決Netty執行緒物件
- java多執行緒5:執行緒間的通訊Java執行緒
- Java多執行緒之執行緒中止Java執行緒
- 多執行緒系列之 執行緒安全執行緒
- iOS 多執行緒之執行緒安全iOS執行緒
- iOS多執行緒之執行緒安全iOS執行緒
- java多執行緒之執行緒的基本使用Java執行緒
- 多執行緒-執行緒控制之守護執行緒執行緒
- Java多執行緒——獲取多個執行緒任務執行完的時間Java執行緒
- Android多執行緒之執行緒池Android執行緒
- java多執行緒系列之執行緒池Java執行緒
- 大話Android多執行緒(三) 執行緒間的通訊機制之HandlerAndroid執行緒
- 多執行緒之Runloop執行緒OOP
- java多執行緒間的通訊Java執行緒
- java--多執行緒之後臺執行緒Java執行緒
- Java多執行緒20:多執行緒下的其他元件之CountDownLatch、Semaphore、ExchangerJava執行緒元件CountDownLatch
- 併發與多執行緒之執行緒安全篇執行緒
- Java多執行緒之守護執行緒實戰Java執行緒
- 多執行緒之NSOperation執行緒
- IOS多執行緒之(GCD)iOS執行緒GC
- iOS 多執行緒之GCDiOS執行緒GC
- java多執行緒之(synchronized)Java執行緒synchronized
- Java多執行緒之FutureTaskJava執行緒
- Java多執行緒之CASJava執行緒
- 多執行緒之共享模型執行緒模型
- Swift多執行緒:使用Thread進行多執行緒間通訊,協調子執行緒任務Swift執行緒thread
- 多執行緒和多執行緒同步執行緒
- JUC之執行緒間的通訊執行緒
- 徹底明白Java的多執行緒-執行緒間的通訊(2)(轉)Java執行緒
- 徹底明白Java的多執行緒-執行緒間的通訊(1)(轉)Java執行緒