如何判斷鎖的物件是誰!永遠知道什麼是鎖,鎖的到底是誰!
深刻理解鎖
第一組
/**
* 8 鎖,就是關於鎖的8個問題
* 1、標準情況下,兩個執行緒列印,發簡訊還是打電話:先列印發簡訊
* 2、sendSms延遲4秒,兩個執行緒列印,發簡訊還是打電話:還是先列印發簡訊
*/
public class Test1 {
public static void main(String[] args) {
Phone phone = new Phone();
//鎖的問題
new Thread(()->{
phone.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone {
//synchronized 鎖的物件是方法的呼叫者
//兩個方法是同一鎖,誰先拿到誰先執行
public synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("發簡訊");
}
public synchronized void call() {
System.out.println("打電話");
}
}
第二組
/**
* 8 鎖,就是關於鎖的8個問題
* 3、增加了一個普通方法後,先列印發簡訊還是hello:先列印普通方法
* 4、兩個物件,兩個同步方法,先列印發簡訊還是打電話:先列印打電話
*/
public class Test2 {
public static void main(String[] args) {
//兩個物件,兩個呼叫者,兩把鎖
Phone2 phone1 = new Phone2();
Phone2 phone2 = new Phone2();
//鎖的問題
new Thread(()->{
phone1.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
// new Thread(()->{
// phone2.hello();
// },"B").start();
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone2 {
//synchronized 鎖的物件是方法的呼叫者
public synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("發簡訊");
}
public synchronized void call() {
System.out.println("打電話");
}
//這裡沒有鎖,不是同步方法,不受鎖的影響
public void hello() {
System.out.println("hello");
}
}
第三組
/**
* 5、增加兩個靜態的同步方法,只有一個物件,先列印:發簡訊
* 6、兩個物件,增加兩個靜態的同步方法,先列印:發簡訊 ,對比不是靜態方法的結果
*/
public class Test3 {
public static void main(String[] args) {
//兩個物件的Class類别範本只有一個,static,鎖的是Class
Phone3 phone1 = new Phone3();
Phone3 phone2 = new Phone3();
//鎖的問題
new Thread(()->{
phone1.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
// Phone3 唯一的一個Class物件
class Phone3 {
//synchronized 鎖的物件是方法的呼叫者
//static 靜態方法
//類一載入就有了,鎖的是Class 模版
public static synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("發簡訊");
}
public static synchronized void call() {
System.out.println("打電話");
}
//這裡沒有鎖,不是同步方法,不受鎖的影響
public void hello() {
System.out.println("hello");
}
}
第四組
/**
* 7、1個靜態的同步方法,1個普通的同步方法,一個物件,先列印:打電話,四秒後發簡訊,因為是兩個鎖,一個是類Class模板的鎖,一個是物件的鎖
* 8、1個靜態的同步方法,1個普通的同步方法,兩個物件,先列印:打電話,四秒後發簡訊,因為是兩個鎖
*/
public class Test4 {
public static void main(String[] args) {
//兩個物件的Class類别範本只有一個,static,鎖的是Class
Phone4 phone1 = new Phone4();
Phone4 phone2 = new Phone4();
//鎖的問題
new Thread(()->{
phone1.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
// Phone3 唯一的一個Class物件
class Phone4 {
//靜態的同步方法 鎖的是Class類别範本
//區分類物件和例項物件
public static synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("發簡訊");
}
//普通的同步方法 鎖的呼叫者
public synchronized void call() {
System.out.println("打電話");
}
//這裡沒有鎖,不是同步方法,不受鎖的影響
public void hello() {
System.out.println("hello");
}
}
小結
new this 具體的物件
static Class 唯一的模板
本作品採用《CC 協議》,轉載必須註明作者和本文連結