Skip to content

Latest commit

 

History

History
103 lines (79 loc) · 2.79 KB

多線程安全.md

File metadata and controls

103 lines (79 loc) · 2.79 KB

多線程安全

安全問題產生的原因

    1. 多個線程在操作共享的數據。
    2. 操作共享數據的線程代碼有多條。
  • 當一個線程在執行操作共享數據的多條代碼過程中,其他線程參與了運算。 就會導致線程安全問題的產生。

sleep(long millis)

  • 釋放資格的同時,釋放執行權
  • 使當前正在執行的線程以指定的毫秒數暫停。
  • millis: 以毫秒為單位的睡眠時間長度。
  • InterruptedException: 如果任何線程中斷當前線程,拋出此異常時,當前線程的中斷狀態將被清除。

安全問題解決

  • 思路: 將多條操作共享數據的線程代碼封裝起來,當有線程在執行這些代碼的時候,其他線程不可以參與運算。 必須要當前線程把這些代碼都執行完畢後,其他線程才可以參與運算。
  • 在 Java 中,用同步代碼塊就可以解決這個問題。

同步

  • 同步好處: 解決了線程安全問題。
  • 同步弊端: 相對降低了效率,因為同步外的線程都會判斷同步鎖。
  • 同步前提: 同步中必須有多個線程並使用同一個鎖。

同步代碼塊(同步鎖)

  • 簡單來講,相當於一道鎖(同步鎖),當一個線程進入同步代碼塊後,鎖住讓其他線程進不來。
  • 格式: synchronized(對象) { //需要被同步的代碼 }

同步函數

  • 使用的鎖是 this (當前對象)
  • 同步函數和同步代碼塊的區別: 同步函數的鎖是固定的 this。 同步代碼塊的鎖是任意的對象。
  • 注意: 建議使用同步代碼塊,同步函數是簡寫。
  • 靜態的同步函數使用的鎖是該函數所屬字節碼文件對象, 可以用 getClass 方法獲取,也可以用當前 類名.class 表示。

Example

public class Ticket extends Thread {
	
	private int num = 10;
	Object obj = new Object();//創建對象傳入同步代碼塊
	
	public void run() {
		
		while(true) {
			
			synchronized(obj) {//簡單來講,相當於一道鎖(同步鎖),讓其他線程進不來
				
				if(num > 0) {//票數不能為負數	
					try {
					
						Thread.sleep(10);//暫停十毫秒
					
					} catch (InterruptedException e) {
										
					}
					System.out.println(Thread.currentThread().getName() + " sale " + num--);
				}
			}
		}
	}
}

public class TicketDemo {

	public static void main(String[] args) {
		
		Ticket t = new Ticket();//創建一個線程任務對象

		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		Thread t3 = new Thread(t);
		Thread t4 = new Thread(t);
		
		t1.start();
		t2.start();
		t3.start();
		t3.start();

	}
}

打印結果

Thread-1 sale 10
Thread-1 sale 9
Thread-1 sale 8
Thread-1 sale 7
Thread-1 sale 6
Thread-2 sale 5
Thread-2 sale 4
Thread-2 sale 3
Thread-2 sale 2
Thread-2 sale 1