11、JUC--線程八鎖
線程八鎖
• 一個對象裏面如果有多個synchronized方法,某一個時刻內,只要一個線程去調用
其中的一個synchronized方法了,其它的線程都只能等待,換句話說,某一個時刻
內,只能有唯一一個線程去訪問這些synchronized方法
• 鎖的是當前對象this,被鎖定後,其它的線程都不能進入到當前對象的其它的
synchronized方法
• 加個普通方法後發現和同步鎖無關
• 換成兩個對象後,不是同一把鎖了,情況立刻變化。
• 都換成靜態同步方法後,情況又變化
• 所有的非靜態同步方法用的都是同一把鎖——實例對象本身,也就是說如果一個實
例對象的非靜態同步方法獲取鎖後,該實例對象的其他非靜態同步方法必須等待獲
取鎖的方法釋放鎖後才能獲取鎖,可是別的實例對象的非靜態同步方法因為跟該實
例對象的非靜態同步方法用的是不同的鎖,所以毋須等待該實例對象已獲取鎖的非
靜態同步方法釋放鎖就可以獲取他們自己的鎖。
• 所有的靜態同步方法用的也是同一把鎖——類對象本身,這兩把鎖是兩個不同的對
象,所以靜態同步方法與非靜態同步方法之間是不會有競態條件的。但是一旦一個
靜態同步方法獲取鎖後,其他的靜態同步方法都必須等待該方法釋放鎖後才能獲取
鎖,而不管是同一個實例對象的靜態同步方法之間,還是不同的實例對象的靜態同
題目判打印的是one還是two?
1、
class Number{ public synchronized void getOne(){ System.out.println("one"); } public synchronized void getTwo(){ System.out.println("two"); } }
測試:
public static void main(String[] args) { Number num= new Number(); new Thread(new Runnable() { @Override public void run() { num.getOne(); } }).start(); new Thread(new Runnable() { @Override public void run() { num.getTwo(); } }).start(); }
兩個普通同部方法,兩個線程標準打印
2、
新增方法讓getOne方法讓其睡眠三秒
class Number{ public synchronized void getOne(){ try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("one"); } public synchronized void getTwo(){ System.out.println("two"); } }
新增Thread.sleep()方法給getOne()
此時得到結果的順序:
3、
新增一個普通方法
class Number{ public synchronized void getOne(){ try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("one"); } public synchronized void getTwo(){ System.out.println("two"); } public void getThree(){ System.out.println("Three"); } }
測試類:
Number num = new Number(); new Thread(new Runnable() { @Override public void run() { num.getOne(); } }).start(); new Thread(new Runnable() { @Override public void run() { num.getTwo(); } }).start(); new Thread(new Runnable() { @Override public void run() { num.getThree(); } }).start();
4、
兩個普通同部方法,兩個Number對象
class Number{ public synchronized void getOne(){ try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("one"); } public synchronized void getTwo(){ System.out.println("two"); } public void getThree(){ System.out.println("Three"); } }
Number num = new Number(); Number num1 = new Number(); new Thread(new Runnable() { @Override public void run() { num.getOne(); } }).start(); new Thread(new Runnable() { @Override public void run() { num1.getTwo(); } }).start();
5、
修改getOne()為靜態同部方法
class Number{ public static synchronized void getOne(){ try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("one"); } public synchronized void getTwo(){ System.out.println("two"); } public void getThree(){ System.out.println("Three"); } }
Number num = new Number(); new Thread(new Runnable() { @Override public void run() { num.getOne(); } }).start(); new Thread(new Runnable() { @Override public void run() { num.getTwo(); } }).start();
6、
修改兩個方法均為靜態同部方法
class Number{ public static synchronized void getOne(){ try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("one"); } public static synchronized void getTwo(){ System.out.println("two"); }
}
Number num = new Number(); //Number num1 = new Number(); new Thread(new Runnable() { @Override public void run() { num.getOne(); } }).start(); new Thread(new Runnable() { @Override public void run() { num.getTwo(); } }).start();
7、
一個靜態同部方法
一個非靜態同部方法
兩個對象
class Number{ public static synchronized void getOne(){ try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("one"); } public synchronized void getTwo(){ System.out.println("two"); } public void getThree(){ System.out.println("Three"); } }
Number num = new Number(); Number num1 = new Number(); new Thread(new Runnable() { @Override public void run() { num.getOne(); } }).start(); new Thread(new Runnable() { @Override public void run() { num1.getTwo(); } }).start();
8、
兩個靜態同部方法
兩個對象
class Number{ public static synchronized void getOne(){ try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("one"); } public static synchronized void getTwo(){ System.out.println("two"); } }
Number num = new Number(); Number num1 = new Number(); new Thread(new Runnable() { @Override public void run() { num.getOne(); } }).start(); new Thread(new Runnable() { @Override public void run() { num1.getTwo(); } }).start();
線程八鎖的關鍵:
1、非靜態方法的鎖默認為this,靜態方法的鎖為對應的Class實例
2、在某一個時刻內,只能有一個線程持有鎖,無論幾個線程
11、JUC--線程八鎖