java內置鎖實現鎖住代碼塊方案(同一個對象或鎖住整個類.class)


我們看一個例子:

class Demo {
public synchronized void test() {
System.out.println("test方法開始執行,當前線程為:"+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("test方法執行完畢,當前線程為:"+Thread.currentThread().getName());
}
}


class MyThread implements Runnable {

@Override
public void run() {
Demo demo = new Demo();
demo.test();
}

}
public class Test {
public static void main(String[] args) {
MyThread myThread = new MyThread();
new Thread(myThread,"子線程A").start();
new Thread(myThread,"子線程B").start();
new Thread(myThread,"子線程C").start();
}
}

  運行結果:

 

 

 

 

  從運行結果我們可以看出,Demo類提供的test同步方法好像並沒有起作用,這是怎么一回事。

  實際上,synchronized(this) 以及非 static 的 synchronized 方法,只能防止多個線程同時執行同一個對象的同步代碼塊。即 synchronized 鎖住的是括號里的對象不是代碼塊

  所以說 synchronized 是一個對象鎖

  當 synchronized 鎖住一個對象后,別的線程如果也想拿到這個對象的鎖,就必須等待這個線程執行完成釋放鎖,才能再次給對象加鎖,這樣才能達到線程同步的目的。所以即使兩個不同的代碼塊都要鎖住同一個對象,那么這兩個代碼段也不能在多線程環境下同時運行,必須等其中一個現將對象鎖釋放掉,另一個才能給對象上鎖。

  所以在上例中,MyThread線程類啟動三次也創建了三個Demo類,並且對其調用,三個不同的對象進入了同步方法中,所以顯示如上結果。

  當一個線程A 進入到同步方法所在的類中,其他線程不能進入該類中的其他類中,因為鎖住的是對象。類比:廁所里有個電視機,某人上廁所時關上了鎖,其他人也不能進來看電視。

  那我們如果想將一段代碼鎖住,使同時有且只有一個對象能訪問該代碼塊應該如何操作。

  這種鎖住代碼塊的的操作叫做全局鎖,可以通過以下兩種途徑實現:

1.1 鎖住同一個對象
class Demo {
public void test() {
// 鎖住進入的方法的對象
synchronized(this) {
System.out.println("test方法開始執行,當前線程為:"+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("test方法執行完畢,當前線程為:"+Thread.currentThread().getName());
}
}
}


class MyThread implements Runnable {
// 為了防止多個線程創建多個對象,所以在類中自己創建一個對象
private Demo demo;
// 在構造方MyThread時將真正的對象傳入
public MyThread(Demo demo) {
this.demo = demo;
}

@Override
public void run() {
this.demo.test();
}

}
public class Test {
public static void main(String[] args) {
// 實際上,整個程序只有這一個對象
// 鎖住了該對象就相當於將 Demo類中的test方法代碼鎖住了,曲線救國實現全局鎖
Demo demo = new Demo();
MyThread myThread = new MyThread(demo);
new Thread(myThread,"子線程A").start();
new Thread(myThread,"子線程B").start();
new Thread(myThread,"子線程C").start();
}
}

 

 

 


1.2 鎖住整個類
class Demo {
public void test() {
// 將 Demo類 作為鎖定的對象,每次只能有一個對象進入該類
synchronized(Demo.class) {
System.out.println("test方法開始執行,當前線程為:"+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("test方法執行完畢,當前線程為:"+Thread.currentThread().getName());
}
}
}


class MyThread implements Runnable {

@Override
public void run() {
// 雖然這里還是存在創建多個對象的問題
// 但是由於test方法這次鎖住了整個類,所以同時有且僅有一個對象能夠進入Demo類中
Demo demo = new Demo();
demo.test();
}

}
public class Test {
public static void main(String[] args) {
MyThread myThread = new MyThread();
new Thread(myThread,"子線程A").start();
new Thread(myThread,"子線程B").start();
new Thread(myThread,"子線程C").start();
}
}

  

 

 

 

 

  當然,使用靜態同步方法也可以實現鎖住整個類的效果。

public static synchronized test() {
// statement
}
————————————————
原文鏈接:https://blog.csdn.net/weixin_40739833/article/details/80293480

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM