微信網(wǎng)站開(kāi)發(fā)有中院管轄呢網(wǎng)站制作公司網(wǎng)站
5. 8鎖現(xiàn)象
如何判斷鎖的是誰(shuí)!鎖到底鎖的是誰(shuí)?
鎖會(huì)鎖住:對(duì)象、Class
深刻理解我們的鎖
問(wèn)題1
兩個(gè)同步方法,先執(zhí)行發(fā)短信還是打電話
public class dome01 {public static void main(String[] args) {Phone phone = new Phone(); new Thread(() -> { phone.sendMs(); }).start();TimeUnit.SECONDS.sleep(1);new Thread(() -> { phone.call(); }).start();}
}class Phone {public synchronized void sendMs() {System.out.println("發(fā)短信");}public synchronized void call() {System.out.println("打電話");}
}
輸出結(jié)果為發(fā)短信打電話
問(wèn)題2:
我們?cè)賮?lái)看:我們讓發(fā)短信 延遲4s
public class dome01 {public static void main(String[] args) throws InterruptedException {Phone phone = new Phone();new Thread(() -> {try {phone.sendMs();} catch (InterruptedException e) {e.printStackTrace();}}).start();TimeUnit.SECONDS.sleep(1);new Thread(() -> { phone.call(); }).start();}
}class Phone {public synchronized void sendMs() throws InterruptedException {TimeUnit.SECONDS.sleep(4);System.out.println("發(fā)短信");}public synchronized void call() {System.out.println("打電話");}
}
結(jié)果:還是先發(fā)短信,然后再打電話!
原因:并不是順序執(zhí)行,而是synchronized 鎖住的對(duì)象是方法的調(diào)用!對(duì)于兩個(gè)方法用的是同一個(gè)鎖,誰(shuí)先拿到誰(shuí)先執(zhí)行,另外一個(gè)等待
問(wèn)題三
加一個(gè)普通方法
public class dome01 {public static void main(String[] args) throws InterruptedException {Phone phone = new Phone();new Thread(() -> {try {phone.sendMs();} catch (InterruptedException e) {e.printStackTrace();}}).start();TimeUnit.SECONDS.sleep(1);new Thread(() -> { phone.hello(); }).start();}
}class Phone {public synchronized void sendMs() throws InterruptedException {TimeUnit.SECONDS.sleep(4);System.out.println("發(fā)短信");}public synchronized void call() {System.out.println("打電話");}public void hello() {System.out.println("hello");}
}
輸出結(jié)果為hello發(fā)短信
原因:hello是一個(gè)普通方法,不受synchronized鎖的影響,不用等待鎖的釋放
問(wèn)題四
如果我們使用的是兩個(gè)對(duì)象,一個(gè)調(diào)用發(fā)短信,一個(gè)調(diào)用打電話,那么整個(gè)順序是怎么樣的呢?
public class dome01 {public static void main(String[] args) throws InterruptedException {Phone phone1 = new Phone();Phone phone2 = new Phone();new Thread(() -> {try {phone1.sendMs();} catch (InterruptedException e) {e.printStackTrace();}}).start();TimeUnit.SECONDS.sleep(1);new Thread(() -> { phone2.call(); }).start();}
}class Phone {public synchronized void sendMs() throws InterruptedException {TimeUnit.SECONDS.sleep(4);System.out.println("發(fā)短信");}public synchronized void call() {System.out.println("打電話");}public void hello() {System.out.println("hello");}
}
輸出結(jié)果打電話發(fā)短信
原因:兩個(gè)對(duì)象兩把鎖,不會(huì)出現(xiàn)等待的情況,發(fā)短信睡了4s,所以先執(zhí)行打電話
問(wèn)題五、六
如果我們把synchronized的方法加上static變成靜態(tài)方法!那么順序又是怎么樣的呢?
(1)我們先來(lái)使用一個(gè)對(duì)象調(diào)用兩個(gè)方法!
答案是:先發(fā)短信,后打電話
(2)如果我們使用兩個(gè)對(duì)象調(diào)用兩個(gè)方法!
答案是:還是先發(fā)短信,后打電話
原因是什么呢? 為什么加了static就始終前面一個(gè)對(duì)象先執(zhí)行呢!為什么后面會(huì)等待呢?
原因是:對(duì)于static靜態(tài)方法來(lái)說(shuō),對(duì)于整個(gè)類Class來(lái)說(shuō)只有一份,對(duì)于不同的對(duì)象使用的是同一份方法,相當(dāng)于這個(gè)方法是屬于這個(gè)類的,如果靜態(tài)static方法使用synchronized鎖定,那么這個(gè)synchronized鎖會(huì)鎖住整個(gè)對(duì)象!不管多少個(gè)對(duì)象,對(duì)于靜態(tài)的鎖都只有一把鎖,誰(shuí)先拿到這個(gè)鎖就先執(zhí)行,其他的進(jìn)程都需要等待!
問(wèn)題七
如果我們使用一個(gè)靜態(tài)同步方法、一個(gè)同步方法、一個(gè)對(duì)象調(diào)用順序是什么
public class dome01 {public static void main(String[] args) throws InterruptedException {Phone phone1 = new Phone();
// Phone phone2 = new Phone();new Thread(() -> {try {phone1.sendMs();} catch (InterruptedException e) {e.printStackTrace();}}).start();TimeUnit.SECONDS.sleep(1);new Thread(() -> { phone1.call(); }).start();}
}class Phone {public static synchronized void sendMs() throws InterruptedException {TimeUnit.SECONDS.sleep(4);System.out.println("發(fā)短信");}public synchronized void call() {System.out.println("打電話");}public void hello() {System.out.println("hello");}
}
輸出結(jié)果打電話發(fā)短信
原因:因?yàn)橐粋€(gè)鎖的是Class類的模板,一個(gè)鎖的是對(duì)象的調(diào)用者。所以不存在等待,直接運(yùn)行。
問(wèn)題八
如果我們使用一個(gè)靜態(tài)同步方法、一個(gè)同步方法、兩個(gè)對(duì)象調(diào)用順序是什么?
public class dome01 {public static void main(String[] args) throws InterruptedException {Phone phone1 = new Phone();Phone phone2 = new Phone();new Thread(() -> {try {phone1.sendMs();} catch (InterruptedException e) {e.printStackTrace();}}).start();TimeUnit.SECONDS.sleep(1);new Thread(() -> { phone2.call(); }).start();}
}class Phone {public static synchronized void sendMs() throws InterruptedException {TimeUnit.SECONDS.sleep(4);System.out.println("發(fā)短信");}public synchronized void call() {System.out.println("打電話");}public void hello() {System.out.println("hello");}
}
輸出結(jié)果打電話發(fā)短信
原因:兩把鎖鎖的不是同一個(gè)東西
小解
new 出來(lái)的 this 是具體的一個(gè)對(duì)象
static Class 是唯一的一個(gè)模板