在上一篇文章中我們講到了如何使用關鍵字synchronized來實現同步訪問。本文我們繼續來探討這個問題,從Java 5之後,在java.util.concurrent.locks包下提供了另外一種方式來實現同步訪問,那就是Lock。
也許有朋友會問,既然都可以通過synchronized來實現同步訪問了,那麼為什麼還需要提供Lock。這個問題將在下面進行闡述。本文先從synchronized的缺陷講起,然後再講述java.util.concurrent.locks包下常用的有哪些類和介面,最後討論以下一些關於鎖的概念方面的東西
以下是本文目錄大綱:
一.synchronized的缺陷
二.java.util.concurrent.locks包下常用的類
三.鎖的相關概念介紹
若有不正之處請多多諒解,並歡迎批評指正。
請尊重作者勞動成果,轉載請標明原文連結:
http://www.cnblogs.com/dolphin0520/p/3923167.html 一.synchronized的缺陷
synchronized是java中的一個關鍵字,也就是說是Java語言內建的特性。那麼為什麼會出現Lock呢。
在上面一篇文章中,我們瞭解到如果一個代碼塊被synchronized修飾了,當一個線程擷取了對應的鎖,並執行該代碼塊時,其他線程便只能一直等待,等待擷取鎖的線程釋放鎖,而這裡擷取鎖的線程釋放鎖只會有兩種情況:
1)擷取鎖的線程執行完了該代碼塊,然後線程釋放對鎖的佔有;
2)線程執行發生異常,此時JVM會讓線程自動釋放鎖。
那麼如果這個擷取鎖的線程由於要等待IO或者其他原因(比如調用sleep方法)被阻塞了,但是又沒有釋放鎖,其他線程便只能乾巴巴地等待,試想一下,這多麼影響程式執行效率。
因此就需要有一種機制可以不讓等待的線程一直無期限地等待下去(比如只等待一定的時間或者能夠響應中斷),通過Lock就可以辦到。
再舉個例子:當有多個線程讀寫檔案時,讀操作和寫操作會發生衝突現象,寫操作和寫操作會發生衝突現象,但是讀操作和讀操作不會發生衝突現象。
但是採用synchronized關鍵字來實現同步的話,就會導致一個問題:
如果多個線程都只是進行讀操作,所以當一個線程在進行讀操作時,其他線程只能等待無法進行讀操作。
因此就需要一種機制來使得多個線程都只是進行讀操作時,線程之間不會發生衝突,通過Lock就可以辦到。
另外,通過Lock可以知道線程有沒有成功擷取到鎖。這個是synchronized無法辦到的。
總結一下,也就是說Lock提供了比synchronized更多的功能。但是要注意以下幾點:
1)Lock不是Java語言內建的,synchronized是Java語言的關鍵字,因此是內建特性。Lock是一個類,通過這個類可以實現同步訪問;
2)Lock和synchronized有一點非常大的不同,採用synchronized不需要使用者去手動釋放鎖,當synchronized方法或者synchronized代碼塊執行完之後,系統會自動讓線程釋放對鎖的佔用;而Lock則必須要使用者去手動釋放鎖,如果沒有主動釋放鎖,就有可能導致出現死結現象。 二.java.util.concurrent.locks包下常用的類
下面我們就來探討一下java.util.concurrent.locks包中常用的類和介面。
1.Lock
首先要說明的就是Lock,通過查看Lock的源碼可知,Lock是一個介面:
| 1 2 3 4 5 6 7 8 |
public interface Lock { void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock( long time, TimeUnit unit) throws InterruptedException; void unlock(); |