Java多线程(4)--线程的同步解决线程安全问题
多線程出現安全問題
問題的原因:
當多條語句在操作同一個線程共享數據時,一個線程對多條語句只執行了一部分,還沒有執行完,另一個線程參與進來執行,導致共享數據的錯誤。
解決辦法:
對多條操作共享數據的語句,只能讓一個線程都執行完,在執行過程中,其他線程不可以參與執行。
Java對于多線程的安全問題提供了專業的解決方式:同步機制
方式一:同步代碼塊
synchronized(同步監視器){//需要被同步的代碼 }說明:
1.操作共享數據的代碼,即為需要被同步的代碼。
2.共享數據:多個線程共同操作的變量,比如: 車票就是共享數據。
3.同步監視器,俗稱:鎖,任何一個類的對象,都可以充當鎖。(但是要求:多個線程必須共用同一把鎖,即同一個對象)(可以考慮用this充當)(可以考慮類.class充當)
示例:
①Runnable接口實現類
②創建并執行多線程
public class TestThread {public static void main(String[] args) {MThread thread = new MThread();Thread curThread1 = new Thread(thread);Thread curThread2 = new Thread(thread);Thread curThread3 = new Thread(thread);curThread1.setName("窗口一");curThread2.setName("窗口二");curThread3.setName("窗口三");curThread1.start();curThread2.start();curThread3.start();} }同步的方式,解決了線程的安全問題。
操作同步代碼時,只能有一 個線程參與, 其他線程等待,相當于是一個單線程的過程,效率低。
注意:在繼承Thread類這種情況下,需要將同步監視器聲明為靜態的,這樣才能保證同一把鎖。
方式二:同步方法
synchronized還可以放在方法聲明中,表示整個方法為同步方法。
public synchronized void show (){ //其實是有一個同步監視器(鎖)this//需要被同步的代碼 }與同步代碼塊使用類似,只是在run()方法中調用該同步方法。
注意:和使用同步代碼塊一樣,在繼承Thread類這種情況下,需要將該同步方法聲明為靜態的,即public static synchronized void show (),此時的同步監視器相當于是當前類.class。
同步方法仍然涉及到同步監視器,只是不需要我們顯式的聲明。
非靜態的同步方法,同步監視器是: this
靜態的同步方法,同步監視器是:當前類本身
方式三:Lock鎖方式
從JDK 5.0開始,Java提供了更強大的線程同步機制——通過顯式定義同步鎖對象來實現同步,同步鎖使用Lock對象充當。
ReentrantLock 類實現了 Lock ,它擁有與 synchronized 相同的并發性和內存語義,在實現線程安全的控制中,比較常用的是ReentrantLock,可以顯式加鎖、釋放鎖。
class A{private final ReentrantLock lock = new ReenTrantLock();public void run(){lock.lock();try{//保證線程安全的代碼;}finally{lock.unlock(); }} }synchronized 與 Lock 的對比:
①Lock是顯式鎖(手動開啟和關閉鎖),synchronized是隱式鎖,出了作用域自動釋放。
②Lock只有代碼塊鎖,synchronized有代碼塊鎖和方法鎖。
③使用Lock鎖,JVM將花費較少的時間來調度線程,性能更好,并且具有更好的擴展性(提供更多的子類)。
總結
以上是生活随笔為你收集整理的Java多线程(4)--线程的同步解决线程安全问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java多线程(3)--线程的生命周期
- 下一篇: Java多线程(5)--线程通信wait