8鎖現象
如何判斷鎖的是誰!永遠的知道什麼鎖,鎖到底鎖的是誰!
深刻了解我們的鎖
1、标準通路,先發送郵件還是短信 Email 鎖是this
2、暫停3S在郵件方法裡,先發送郵件還是短信 Email 鎖是this
3、新增hello普通方法,先發送郵件還是hello hello 加個普通方法後發現和同步鎖無關
4、有兩部手機,先發送郵件還是短信 EMS 鎖是兩個不同的this,但是需要隔4s才能發送email
5、兩個靜态同步方法,有一部手機,先發送郵件還是短信 Email 鎖的是同一個Class對象
6、一個普通同步方法,一個靜态同步方法,一部手機,先發送郵件還是短信 EMS 兩個鎖,一個是this,一個是Class,但是需要隔4s才能發送email
7、兩個靜态同步方法,有2部手機,先發送郵件還是短信 Email 鎖的是同一個Class對象
8、一個普通同步方法,一個靜态同步方法,2部手機,先發送郵件還是短信 EMS 兩個鎖,一個是this,一個是Class,但是需要隔4s才能發送email
-
标準情況下 是先sendEmail() 還是先sendEMS()?
答案:
sendEmail
解釋:被 synchronized 修飾的方式,鎖的對象是方法的調用者
是以說這裡兩個方法調用的對象是同一個,先調用的先執行!
import java.util.concurrent.TimeUnit; public class LockDemo1 { public static void main(String[] args) throws InterruptedException { Phone1 phone1 = new Phone1(); new Thread(()->{ phone1.sendEmail(); },"A").start(); TimeUnit.SECONDS.sleep(2); new Thread(()->{ phone1.sendEMS(); },"B").start(); } } class Phone1{ public synchronized void sendEmail(){ System.out.println("senEmail"); } public synchronized void sendEMS(){ System.out.println("sendEMS"); } }
-
sendEmail()休眠3s後 是先sendEmail() 還是先sendEMS()?
答案:
sendEmail
解釋:被 synchronized 修飾的方式,鎖的對象是方法的調用者
是以說這裡兩個方法調用的對象是同一個,先調用的先執行!
import java.util.concurrent.TimeUnit; public class LockDemo2 { public static void main(String[] args) throws InterruptedException { Phone2 phone2 = new Phone2(); new Thread(()->{ try { phone2.sendEmail(); } catch (InterruptedException e) { e.printStackTrace(); } },"A").start(); TimeUnit.SECONDS.sleep(2); new Thread(()->{ phone2.sendEMS(); },"B").start(); } } class Phone2{ public synchronized void sendEmail() throws InterruptedException { TimeUnit.SECONDS.sleep(3); System.out.println("sendEmail"); } public synchronized void sendEMS(){ System.out.println("sendEMS"); } }
-
一部手機, 被synchronized 修飾的方式和普通方法 先執行sendEmail() 還是 sendEMS()
答案:
解釋:新增加的這個方法沒有 synchronized 修飾,不是同步方法,不受鎖的影響!sendEMS
import java.util.concurrent.TimeUnit; public class LockDemo3 { public static void main(String[] args) throws InterruptedException { Phone3 phone3 = new Phone3(); new Thread(()->{ try { phone3.sendEmail(); } catch (InterruptedException e) { e.printStackTrace(); } },"A").start(); TimeUnit.SECONDS.sleep(2); new Thread(()->{ phone3.sendEMS(); },"B").start(); } } class Phone3{ public synchronized void sendEmail() throws InterruptedException { TimeUnit.SECONDS.sleep(3); System.out.println("sendEmail"); } // 沒有synchronized 沒有static 就是普通方式 public void sendEMS(){ System.out.println("sendEMS"); } }
-
兩部手機,被synchronized 修飾的不同方法 先執行sendEmail() 還是sendEMS()?
答案:
sendEMS
解釋:被synchronized 修飾的不同方法 鎖的對象是調用者
這裡鎖的是
,所有互不影響兩個不同的調用者
import java.util.concurrent.TimeUnit; public class LockDemo4 { public static void main(String[] args) throws InterruptedException { Phone4 phoneA = new Phone4(); Phone4 phoneB = new Phone4(); new Thread(()->{ try { phoneA.sendEmail(); } catch (InterruptedException e) { e.printStackTrace(); } },"A").start(); TimeUnit.SECONDS.sleep(2); new Thread(()->{ phoneB.sendEMS(); },"B").start(); } } class Phone4{ public synchronized void sendEmail() throws InterruptedException { TimeUnit.SECONDS.sleep(3); System.out.println("sendEmail"); } public synchronized void sendEMS(){ System.out.println("sendEMS"); } }
-
一部手機,兩個靜态同步方法 都被synchronized 修飾 是先sendEmail() 還是sendEMS()?
答案:
解釋:隻要方法被 static 修飾,鎖的對象就是sendEmial
Class模闆對象,這個則全局唯一
!
是以說這裡是同一個鎖,并不是因為synchronized 這裡程式會從上往下依次執行
import java.util.concurrent.TimeUnit; public class LockDemo5 { public static void main(String[] args) throws InterruptedException { Phone5 phone5 = new Phone5(); new Thread(()->{ try { phone5.sendEmail(); } catch (InterruptedException e) { e.printStackTrace(); } },"A").start(); TimeUnit.SECONDS.sleep(2); new Thread(()->{ phone5.sendEMS(); },"B").start(); } } class Phone5{ public static synchronized void sendEmail() throws InterruptedException { TimeUnit.SECONDS.sleep(3); System.out.println("sendEmail"); } public static synchronized void sendEMS(){ System.out.println("sendEMS"); } }
-
一部手機,被synchronized 修飾的普通方法和靜态方法 是先sendEmail() 還是 sendEMS()?
答案:
解釋:sendEMS
隻要被static修飾鎖的是class模闆
, 而synchronized 鎖的是調用的對象
這裡是兩個鎖互不影響,按時間先後執行
import java.util.concurrent.TimeUnit; public class LockDemo6 { public static void main(String[] args) throws InterruptedException { Phone6 phone6 = new Phone6(); new Thread(()->{ try { phone6.sendEmail(); } catch (InterruptedException e) { e.printStackTrace(); } },"A").start(); TimeUnit.SECONDS.sleep(2); new Thread(()->{ phone6.sendEMS(); },"B").start(); } } class Phone6{ public static synchronized void sendEmail() throws InterruptedException { TimeUnit.SECONDS.sleep(3); System.out.println("sendEmail"); } public synchronized void sendEMS(){ System.out.println("sendEMS"); } }
- 兩部手機,同被static+synchronized 修飾的兩個方法,是先sendEmail()還是sendEMS()?
答案:
sendEmail
解釋:隻要方法被 static 修飾,鎖的對象就是 Class模闆對象,這個則全局唯一
是以說這裡是同一個鎖,并不是因為synchronized
import java.util.concurrent.TimeUnit;
public class LockDemo7 {
public static void main(String[] args) throws InterruptedException {
Phone7 phoneA = new Phone7();
Phone7 phoneB = new Phone7();
new Thread(()->{
try {
phoneA.sendEmail();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
TimeUnit.SECONDS.sleep(2);
new Thread(()->{
phoneB.sendEMS();
},"B").start();
}
}
class Phone7{
public static synchronized void sendEmail() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println("sendEmail");
}
public static synchronized void sendEMS(){
System.out.println("sendEMS");
}
}
-
兩部手機,一個被static+synchronized 修飾的方法和普通的synchronized方法,先執行sendEmail()還是sendEMS()?
答案:
sendEMS()
解釋: 隻要被static 修飾的鎖的就是整個class模闆
這裡一個鎖的是class模闆 一個鎖的是調用者
是以鎖的是兩個對象 互不影響
import java.util.concurrent.TimeUnit; public class LockDemo8 { public static void main(String[] args) throws InterruptedException { Phone8 phoneA = new Phone8(); Phone8 phoneB = new Phone8(); new Thread(()->{ try { phoneA.sendEmail(); } catch (InterruptedException e) { e.printStackTrace(); } },"A").start(); TimeUnit.SECONDS.sleep(2); new Thread(()->{ phoneB.sendEMS(); },"B").start(); } } class Phone8{ public static synchronized void sendEmail() throws InterruptedException { TimeUnit.SECONDS.sleep(3); System.out.println("sendEmail"); } public synchronized void sendEMS(){ System.out.println("sendEMS"); } }
小結
new this 具體的一個手機
static Class 唯一的一個模版