【Java多執行緒】synchronized與執行緒安全
阿新 • • 發佈:2019-01-30
介紹
修飾方法:一個執行緒去呼叫一個加synchronized的方法的時候,會獲得該物件的 物件鎖
。
修飾靜態方法:一個執行緒去呼叫一個既加static,又加synchronized的方法的時候,會獲得該物件的 類鎖
。
修飾程式碼塊:
①加物件鎖
:
synchronized (this){}
②加類鎖
:
synchronized (ObjectLock.class) {}
③任意物件鎖
:
private Object lock = new Object();
synchronized (lock) {}
④String鎖(不建議使用)
synchronized ("字串常量") {}
基本概念
髒讀:
兩個執行緒去操作一個物件的兩個方法的時候(一個加鎖,另一個不加鎖。兩個方法又同時操作該物件的成員變數),就可能出現操作的出來的結果不一致的問題。原理:是兩個執行緒呼叫方法操作的不是真正成員變數,而是自己 執行緒棧幀
裡的副本
。
Synchronized異常處理
①如果對方法的後續操作有關聯關係的話:記錄日誌,並在 try-catch 裡面丟擲異常;
②如果沒有關聯關係,記錄日誌,並在 try-catch 裡面繼續continue;
鎖重入:
①同一個物件,不同方法間的鎖重入
public synchronized void method1(){
System.out.println("method1..");
method2();
}
public synchronized void method2(){
System.out.println("method2..");
method3();
}
public synchronized void method3(){
System.out.println("method3..");
}
public static void main (String[] args) {
final SyncDubbo1 sd = new SyncDubbo1();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
sd.method1();
}
});
t1.start();
}
②子類父類間的重入
static class Main {
public int i = 10;
public synchronized void operationSup(){
try {
i--;
System.out.println("Main print i = " + i);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Sub extends Main {
public synchronized void operationSub(){
try {
while(i > 0) {
i--;
System.out.println("Sub print i = " + i);
Thread.sleep(100);
this.operationSup();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
Sub sub = new Sub();
sub.operationSub();
}
});
t1.start();
}