區分同步代碼塊、靜態同步方法、非靜態同步方法的鎖
阿新 • • 發佈:2019-03-17
同步 zed 方法 extends his 類名 ole true 解決
同步代碼塊、靜態同步方法、非靜態同步方法的鎖分別是:
- 同步代碼塊可以使用自定義的Object對象,也可以使用this或者當前類的字節碼文件(類名.class);
- 靜態同步方法的鎖是當前類的字節碼文件(類名.class);
- 非靜態同步方法的鎖是this;
證明方法:
- 兩個線程之間實現同步,一個線程使用同步代碼塊,一個線程使用同步方法。
- 如果這兩個線程同步了,說明了使用的是同一個鎖;
創建線程類(以售票為例)
/** * @methodDesc 售票線程類 */ public class ThreadTrain extends Thread { // 總共又100張 private static int trainCount = 100; protected static boolean flag = true; @Override public void run() { while (trainCount > 0) { if (flag) { // 執行同步代碼塊,this鎖 System.out.println("flag==="+flag); // 出售火車票 sale1(); }else { System.out.println("flag==="+flag); // 出售火車票 sale11(); } flag = !flag; } } // 同步代碼塊 public void sale1() { // 同步代碼塊,包裹需要解決線程安全問題的代碼塊,兩個線程同時訪問 synchronized (this) { // 只能有一個線程進行訪問,必須拿到鎖的時候才能訪問 if (trainCount > 0) { // 不加判斷,會出現出售第101張票的情況 System.out.println(Thread.currentThread().getName() + ", 出售第" + (100 - trainCount + 1) + "張票"); trainCount--; } } } // 靜態同步代碼塊 public void sale2() { // 同步代碼塊,包裹需要解決線程安全問題的代碼塊,兩個線程同時訪問 synchronized (ThreadTrain.class) { // 只能有一個線程進行訪問,必須拿到鎖的時候才能訪問 if (trainCount > 0) { // 不加判斷,會出現出售第101張票的情況 System.out.println(Thread.currentThread().getName() + ", 出售第" + (100 - trainCount + 1) + "張票"); trainCount--; } } } // 同步方法 public synchronized void sale11() { if (trainCount > 0) { // 不加判斷,會出現出售第101張票的情況 System.out.println(Thread.currentThread().getName() + ", 出售第" + (100 - trainCount + 1) + "張票"); trainCount--; } } // 靜態同步方法 public static synchronized void sale22() { if (trainCount > 0) { // 不加判斷,會出現出售第101張票的情況 System.out.println(Thread.currentThread().getName() + ", 出售第" + (100 - trainCount + 1) + "張票"); trainCount--; } } }
創建測試類
/** * @methodDesc 多線程模擬售票問題 */ public class ThreadDemo { public static void main(String[] args) throws InterruptedException { // 創建售票線程對象 ThreadTrain train1 = new ThreadTrain(); // 創建多個售票窗口,並給其取別名 Thread t1 = new Thread(train1, "窗口1"); Thread t2 = new Thread(train1, "窗口2"); t1.start(); t2.start(); } }
驗證方法
- 驗證非靜態同步方法,修改run方法為
public void run() { while (trainCount > 0) { if (flag) { // 執行同步代碼塊,this鎖 System.out.println("flag==="+flag); // 出售火車票 sale1(); }else { System.out.println("flag==="+flag); // 出售火車票 sale11(); } flag = !flag; } }
- 驗證靜態同步方法,修改run方法為
public void run() {
while (trainCount > 0) {
if (flag) { // 執行同步代碼塊,this鎖
System.out.println("flag==="+flag);
// 出售火車票
sale2();
}else {
System.out.println("flag==="+flag);
// 出售火車票
sale22();
}
flag = !flag;
}
}
區分同步代碼塊、靜態同步方法、非靜態同步方法的鎖