java執行緒同步:synchronized關鍵字,Lock介面以及可重
多執行緒環境下,必須考慮執行緒同步的問題,這是因為多個執行緒同時訪問變數或者資源時會有執行緒爭用,比如A執行緒讀取了一個變數,B執行緒也讀取了這個變數,然後他們同時對這個變數做了修改,寫回到記憶體中,由於是同時做修改,就會導致修改的狀態不一致.
用一個實際的例子來說明執行緒同步的必要性:
package cn.outofmemory.locks; public class LockDemo implements Runnable { private int counter = 0; public void run() { int loopTimes = 10000; while (loopTimes > 0) { counter ++; loopTimes --; } } public static void main(String[] args) throws InterruptedException { LockDemo demo = new LockDemo(); Thread[] threads = new Thread[]{ new Thread(demo), new Thread(demo),new Thread(demo), new Thread(demo),new Thread(demo) }; for (Thread t : threads) { t.start(); } for (Thread t : threads) { t.join(); } System.out.println("demo's counter is " + demo.counter); } }
這段程式碼中的LockDemo類實現了Runnable介面,在run方法中對其私有變數counter遞加了10000次。在main方法中我們首先初始化了一個LockDemo物件,然後初始化了5個執行緒,這5個執行緒公用一個LockDemo的例項。
然後我們一次啟動這5個執行緒,然後透過join等待所有執行緒結束,最後輸出demo例項的counter值來。
執行程式,我這兒得到這樣一個輸出結果:
demo's counter is 44041
本來5個執行緒每個執行緒遞加10000次,應該得到的結果是50000,而實際的結果是44041.
如果你也執行此程式有可能會得到不一樣的結果。這取決於這5個執行緒造成了多少次的衝突。從我的輸出結果看,這段程式的5個執行緒造成了大約6000次的記憶體爭用衝突。
在實際應用中,這是不可用的。
改程式序,避免衝突
我們可以分析一下,這5個執行緒的衝突出現在什麼地方,他們公用了demo物件,同時對demo物件的成員變數counter做遞加,也就是說衝突出現在對counter遞加這一步上。
我們在這一步操作上加上synchronzied關鍵字,讓5個執行緒執行到對counter++這步程式碼時單獨執行,應該就可以解決問題了。
修改後的run方法程式碼:
public void run() { int loopTimes = 10000; while (loopTimes > 0) { synchronized (this) { counter ++; } loopTimes --; } }
我們再次執行程式會得到如下確定的輸出結果:
demo's counter is 50000
這次得到的結果是符合我們的預期的,我們透過synchronized關鍵字解決了問題。
synchronized關鍵字是jvm虛擬機器的關鍵字,在java.util.concurrent.locks名稱空間中還有一個Lock介面,和Lock介面的實現類ReentrantLock(可重入鎖)。 ReentrantLock可以實現和synchronized關鍵字相同的功能,而且更為靈活,在極端的情況下效能會更好一些。
我們看下使用可重入鎖ReentrantLock解決執行緒同步的方法:
private final Lock lock = new ReentrantLock(); public void run() { int loopTimes = 10000; while (loopTimes > 0) { try { lock.lock(); counter ++; } finally { lock.unlock(); } loopTimes --; } }
我們在LockDemo中新增了一個final的成員變數lock,它是一個ReentrantLock的例項。 在run方法中,在counter++這行程式碼兩邊加上了try .. finally ..語句,
當執行緒執行到try塊之後,首先透過lock.lock()獲得鎖,獲得鎖之後再執行counter++,最後在finally語句塊中透過lock的unlock方法釋放鎖。
我們可以執行修改後的程式碼,輸出如下:
demo's counter is 50000
輸出結果符合邏輯預期。
synchronized獲得的內部鎖存在一定的侷限
1. 不能中斷一個正在試圖獲得鎖的執行緒
2. 試圖獲得鎖時不能像trylock那樣設定超時時間
3. 每個鎖只有單一的條件,不像condition那樣可以設定多個
synchronzied關鍵字和可重入鎖ReentrantLock選擇的最佳實踐:
1. 如果synchronized關鍵字適合程式,儘量使用它,可以減少程式碼出錯的機率和程式碼數量
2. 如果特別需要Lock/Condition結構提供的獨有特性時,才使用他們
3. 許多情況下可以使用java.util.concurrent包中的一種機制,它會為你處理所有的加鎖情況
原文連結:http://outofmemory.cn/java/java.util.concurrent/synchronized-locks-Lock-ReentrantLock
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3016/viewspace-2811197/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java多執行緒之執行緒同步【synchronized、Lock、volatitle】Java執行緒synchronized
- JAVA-多執行緒(關鍵字:synchronized)Java執行緒synchronized
- Java併發程式設計序列之執行緒間通訊-synchronized關鍵字-volatile關鍵字Java程式設計執行緒synchronized
- 多執行緒與高併發(三)synchronized關鍵字執行緒synchronized
- 執行緒關鍵字、鎖、同步集合筆記執行緒筆記
- @Java | Thread & synchronized – [ 執行緒同步鎖 基本使用]Javathreadsynchronized執行緒
- Java多執行緒(二)volatile關鍵字Java執行緒
- java多執行緒4:volatile關鍵字Java執行緒
- Java關鍵字(八)——synchronizedJavasynchronized
- JUC之Lock介面以及Synchronized回顧synchronized
- Java多執行緒學習(三)volatile關鍵字Java執行緒
- Java中的執行緒安全:從synchronized到Lock的深入理解Java執行緒synchronized
- 10-Java中共享記憶體可見性以及synchronized和volatile關鍵字Java記憶體synchronized
- Java多執行緒(三):SynchronizedJava執行緒synchronized
- java多執行緒之(synchronized)Java執行緒synchronized
- java多執行緒3:synchronizedJava執行緒synchronized
- java 執行緒淺解03[執行緒同步以及經典死鎖]Java執行緒
- Volatile關鍵字與執行緒安全執行緒
- 多執行緒之volative關鍵字執行緒
- 是時候來嘮一嘮synchronized關鍵字了,Java多執行緒的必問考點!synchronizedJava執行緒
- java基礎:執行緒與程式;執行緒的分工,協作,互斥;volatile關鍵字Java執行緒
- Java併發——關鍵字synchronized解析Javasynchronized
- Java多執行緒程式設計筆記2:synchronized同步方法Java執行緒程式設計筆記synchronized
- synchronized 關鍵字synchronized
- java synchronized 保護執行緒安全Javasynchronized執行緒
- Java多執行緒之二(Synchronized)Java執行緒synchronized
- Android小知識-Java多執行緒相關(Lock使用)AndroidJava執行緒
- Java高併發之synchronized關鍵字Javasynchronized
- java 多執行緒 –同步Java執行緒
- java 多執行緒 --同步Java執行緒
- 6.JUC執行緒高階-Lock同步鎖執行緒
- Java多執行緒之synchronized理論Java執行緒synchronized
- Java多執行緒——synchronized的使用示例Java執行緒synchronized
- Java多執行緒之synchronized詳解Java執行緒synchronized
- 使用 Synchronized 關鍵字synchronized
- java多執行緒:執行緒同步synchronized(不同步的問題、佇列與鎖),死鎖的產生和解決Java執行緒synchronized佇列
- synchronized 同步執行緒 單例設計模式+double checkingsynchronized執行緒單例設計模式
- Java:synchronized關鍵字引出的多種鎖Javasynchronized