Java多執行緒中的物件互斥鎖
阿新 • • 發佈:2019-02-05
1、為什麼會有鎖?
在看執行緒同步的問題之前,我們先看一個生活中的小例子:
我拿著銀行卡去ATM取錢,假如我的卡里有3000塊,我要取走2000,這個時候,ATM會去銀行的資料庫裡查詢我的賬戶是否有2000以上的餘額,如果有,就會讓我取走,不幸的是,這個時候,我女朋友也來銀行取錢,只不過她在前臺取錢,她直接取走了3000,這個時候我的卡里已經沒錢了,而我也肯定也不能取出2000了。
我們可以這樣想,上面例子中的我和女朋友是兩個執行緒,我們在訪問同一塊資源,也就是一個賬戶,這個情況下,是不允許在一個執行緒訪問的時候,另一個執行緒來打斷的,就像我在取錢的時候,我女朋友是不能取的,不能打斷我。
我們先來看一段程式碼:
public class TestThread01 implements Runnable{ Timer timer = new Timer(); public static void main(String[] args) { TestThread01 t = new TestThread01(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t1.setName("t1"); t2.setName("t2"); t1.start(); t2.start(); } public void run(){ timer.add(Thread.currentThread().getName()); } } class Timer{ private static int num = 0; public static void add(String name){ num++; try { Thread.sleep(1); } catch (InterruptedException e) { } System.out.println(name +":你是第"+num+"使用timer的執行緒"); } }
上面的程式碼我們就能看出兩個執行緒去訪問同一個資源,也就是timer的add方法,看一下執行結果:
t1:你是第2使用timer的執行緒
t2:你是第2使用timer的執行緒
結果為什麼是這樣呢?
我們分析一下:
t1啟動,訪問add方法,num++變為1,這時,t1睡眠,t2啟動,t2訪問add,num是1,++之後變為2,t2睡眠,t1再繼續訪問,列印“t1:你是第2使用timer的執行緒”,然後t1結束,t2繼續列印“t2:你是第2使用timer的執行緒”。
我們這就見到了執行緒的打斷,有的人可能會說是因為sleep了一毫秒,所以才會這樣,其實不然,如果沒有sleep,也有可能會被打斷,也有可能會正確執行。
2、物件互斥鎖的用法?
解決方法01:給可能競爭的資源物件加上互斥鎖,synchronized (this),鎖定當前物件。
class Timer{
private static int num = 0;
public void add(String name){
synchronized (this) {
num++;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
System.out.println(name +":你是第"+num+"使用timer的執行緒");
}
}
}
這時的執行結果:
t1:你是第1使用timer的執行緒
t2:你是第2使用timer的執行緒
解決方法02:給競爭的方法加上鎖
class Timer{
private static int num = 0;
public synchronized void add(String name){
num++;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
System.out.println(name +":你是第"+num+"使用timer的執行緒");
}
}
結果也是對的。