C# Dictionary
阿新 • • 發佈:2021-06-16
執行緒的同步
執行緒的生命週期
同步
在Java中,我們通過同步機制,來解決執行緒的安全問題。
方法一:同步程式碼塊
synchronized(同步監視器){
需要被同步的程式碼
}
說明
-
操作共享資料的程式碼,即為需要被同步的程式碼
-
共享資料:多個執行緒共同操作的變數
-
同步監視器:俗稱:鎖。任何一個物件,都可以充當鎖。
要求:多個執行緒必須公用同一把鎖。
舉例
package com.yicurtain.THREAD; //三個視窗賣100張票,使用同步程式碼塊解決執行緒的安全問題 class window implements Runnable{ private int ticket=100; Object object=new Object(); @Override public void run() { while(true) { synchronized (object) { if (ticket > 0) { System.out.println(Thread.currentThread().getName() + ":" + ticket); ticket--; } else { break; } } } } } public class WindowTest { public static void main(String[] args) { window window = new window(); Thread t1 = new Thread(window); Thread t2 = new Thread(window); Thread t3 = new Thread(window); t1.setName("執行緒1"); t2.setName("執行緒2"); t3.setName("執行緒3"); t1.start(); t2.start(); t3.start(); } }
方法二:同步方法
如果操作共享資料的程式碼完整的宣告在一個方法中,我們不妨將此方法宣告為同步的.
舉例
package com.yicurtain.THREAD; //三個視窗賣100張票,使用同步方法解決執行緒的安全問題 class window1 implements Runnable{ private int ticket=100; Object object=new Object(); @Override public void run() { while(true) { show(); } } public synchronized void show(){ if (ticket > 0) { System.out.println(Thread.currentThread().getName() + ":" + ticket); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } ticket--; } } } public class WindowTest1 { public static void main(String[] args) { window1 window1 = new window1(); Thread t1 = new Thread(window1); Thread t2 = new Thread(window1); Thread t3 = new Thread(window1); t1.setName("執行緒1"); t2.setName("執行緒2"); t3.setName("執行緒3"); t1.start(); t2.start(); t3.start(); } }
總結
- 同步方法仍然涉及到同步監視器,只是不需要我們顯示的宣告。
- 非靜態的同步方法,同步監視器是:this
- 靜態的同步方法,同步監視器是:當前類本身
死鎖
- 不同的執行緒分別佔用對方需要的同步資源不放棄,都在等待對方放棄
自己需要的同步資源,就形成了執行緒的死鎖 - 出現死鎖後,不會出現異常,不會出現提示,只是所有的執行緒都處於
阻塞狀態,無法繼續
方式三:lock鎖
- 例項化Reentrantlock
- 將要執行的程式碼用try{lock.lock}-finally{lock.unlock}包住
- 然後執行
舉例
package com.yicurtain.THREAD; import java.util.concurrent.locks.ReentrantLock; //三個視窗賣100張票,使用lock解決執行緒的安全問題 class window2 implements Runnable{ private int ticket=100; ReentrantLock lock = new ReentrantLock(); @Override public void run() { while(true) { try{ lock.lock(); if (ticket > 0) { System.out.println(Thread.currentThread().getName() + ":" + ticket); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } ticket--; } else { break; } }finally { lock.unlock(); } } } } public class WindowTest2 { public static void main(String[] args) { window2 window2 = new window2(); Thread t1 = new Thread(window2); Thread t2 = new Thread(window2); Thread t3 = new Thread(window2); t1.setName("執行緒1"); t2.setName("執行緒2"); t3.setName("執行緒3"); t1.start(); t2.start(); t3.start(); } }