Java鎖的機制

鎖的機制

以下代碼以使用手機發郵件和發短信爲例
線程的調度不是從上到下,而是和CPU相關。
兩個線程在訪問資源類的時候不是同時進入,鎖是鎖的當前對象,一旦A中鎖住了方法sendEmail,則B只能等待A執行完方法後才能執行sendMessage
1、標準訪問

// 資源類
class Phone{
	public synchronized void sendMessage() throw Exception{
		System.out.println("*********sendMessage");
	}
	public synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
}
// 用於執行線程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人爲讓A線程先於B線程執行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		phone.sendMessage();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

執行結果:一個對象裏面如果有多個synchronized 方法,某一時刻內,只要一個線程去調用了一個synchronized方法,其它線程只能等待。
也就是說某一時刻內,只能有唯一一個線程去訪問這些synchronized方法。

*****sendEmail
*********sendMessage

2、在郵件方法中暫停4S

// 資源類
class Phone{
	public synchronized void sendMessage() throw Exception{
		//暫停4秒,此方法來自Java.util.concurent包
		TimeUnit.Seconds.sleep(4);
		System.out.println("*********sendMessage");
	}
	public synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
}
// 用於執行線程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人爲讓A線程先於B線程執行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		phone.sendMessage();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

執行結果:

*****sendEmail
*********sendMessage

3、新增普通方法sayHello

// 資源類
class Phone{
	public synchronized void sendMessage() throw Exception{
		//暫停4秒,此方法來自Java.util.concurent包
		TimeUnit.Seconds.sleep(4);
		System.out.println("*********sendMessage");
	}
	public synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
	public void sayHello() throw Exception{
	System.out.println("*******sayHello");
	}
}
// 用於執行線程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人爲讓A線程先於B線程執行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		//普通方法
		phone.sayHello();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

執行結果:

*******sayHello
*****sendEmail

4、兩部手機

// 資源類
class Phone{
	public synchronized void sendMessage() throw Exception{
		//暫停4秒,此方法來自Java.util.concurent包
		TimeUnit.Seconds.sleep(4);
		System.out.println("*********sendMessage");
	}
	public synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
}
// 用於執行線程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  Phone phone2=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人爲讓A線程先於B線程執行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		//第二部手機發短信
		phone2.sendMessage();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

執行結果:換了對象,不是同一個資源類,所以情況發生了變化,不同的鎖

*********sendMessage
*****sendEmail

5、兩個靜態同步方法,同一部手機

// 資源類
class Phone{
	public static synchronized void sendMessage() throw Exception{
		//暫停4秒,此方法來自Java.util.concurent包
		TimeUnit.Seconds.sleep(4);
		System.out.println("*********sendMessage");
	}
	public static synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
}
// 用於執行線程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人爲讓A線程先於B線程執行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		//同一部手機調用靜態同步方法
		phone.sendMessage();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

執行結果:由於static是修飾類的,加鎖後,是將整個class鎖住,static修飾的鎖屬於全局鎖,而非對象鎖

*****sendEmail
*********sendMessage

6、兩個靜態同步方法,兩部手機

// 資源類
class Phone{
	public static synchronized void sendMessage() throw Exception{
		//暫停4秒,此方法來自Java.util.concurent包
		TimeUnit.Seconds.sleep(4);
		System.out.println("*********sendMessage");
	}
	public static synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
}
// 用於執行線程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  Phone phone2=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人爲讓A線程先於B線程執行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		//第二部手機調用發短信的方法
		phone2.sendMessage();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

執行結果:由於static是修飾類的,加鎖後,是將整個class鎖住,static修飾的鎖屬於全局鎖,而非對象鎖。對於靜態同步方法,鎖的是當前class

*****sendEmail
*********sendMessage

7、一個靜態同步方法,一個普通同步方法

// 資源類
class Phone{
	public static synchronized void sendMessage() throw Exception{
		//暫停4秒,此方法來自Java.util.concurent包
		TimeUnit.Seconds.sleep(4);
		System.out.println("*********sendMessage");
	}
	public synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
}
// 用於執行線程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人爲讓A線程先於B線程執行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		//調用普通同步方法
		phone.sendMessage();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

執行結果:鎖的對象是不一樣的,一個 鎖的是當前對象,另一個鎖的是整個class。

*********sendMessage
*****sendEmail

8、一個靜態同步方法,一個普通方法,兩部手機

// 資源類
class Phone{
	public static synchronized void sendMessage() throw Exception{
		//暫停4秒,此方法來自Java.util.concurent包
		TimeUnit.Seconds.sleep(4);
		System.out.println("*********sendMessage");
	}
	public synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
}
// 用於執行線程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  Phone phone2=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人爲讓A線程先於B線程執行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		//調用普通同步方法
		phone2.sendMessage();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

執行結果:全局鎖和對象鎖是兩個不同的東西,實際上並無關係。一個是小米工廠,一個是小米手機

*********sendMessage
*****sendEmail
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章