synchronized與lock 都是用來實現線程同步的鎖,synchronized對象鎖,lock是一個接口,她的實現有reentrantlock互斥鎖以及ReentrantReadWriteLock共享鎖。
這里說明一下ReentrantReadWriteLock共享鎖,所謂共享就是該鎖提供讀讀鎖共享,即可以多個線程共享一個讀取鎖,但是讀寫鎖以及讀讀鎖是互斥的。
看到網上有好多介紹介紹鎖的種類的,有對象鎖、互斥鎖、共享鎖以及公平鎖和非公平鎖,但是說明都不夠詳細了然,在這里用直白的說法記錄一下,以供查閱,
對象鎖:一般指的是synchronized這個鎖,這個鎖和對象有關,而且每個對象都會有個隱形的監視器,用於線程的同步,和這個對象線程交互的方法一般有wait和notify及notifyall,
調用wait方法,線程進入對象的監視器等待其他線程調用notify或notifyall,需要注意的是wait與notify或notifyall不能精確喚醒特定的線程,關於這個鎖的用法,請參考這篇文章。
互斥鎖:字面理解相互排斥的,即兩個線程獲得鎖是互斥的,一個線程獲得了鎖,其他線程在此線程釋放鎖之前是不能獲得鎖的,java提供了一個互斥鎖為reentrantlock,該鎖是可以重入的
重入就是指,線程獲得了鎖之后,此線程可以進入任一其他方法中關於這個對象的鎖。我們知道synchronized通過wait和notify等實現線程之間的交互,那么reentrantlock是通過
什么實現交互的呢,在這里就引入了api中一個重要的接口Condition,condition是什么呢,Condition
將 Object
監視器方法(wait
、notify
和 notifyAll
)分解成截然不同的對象,
以便通過將這些對象與任意 Lock
實現組合使用,為每個對象提供多個等待 set(wait-set)。其中,Lock
替代了 synchronized
方法和語句的使用,Condition
替代了 Object 監視
器方法的使用。這個是官網對condition的解釋,可以看出來condition提供的功能和wait與notify是一樣的,只不過condition用於lock中,而wait與notify是和synchronized一起使用
,這里需要說明的就是,condition提供的等待與喚醒機制,更明確指出wait哪一個線程,喚醒哪一個線程,關於Reentrantlock與condition的用法,請參考這篇文章
共享鎖:共享鎖前面已經講過,就是多個線程可以共享鎖,這里指的就是lock的實現類ReentrantReadWriteLock,ReentrantReadWriteLock分為讀鎖與寫鎖,這里鎖的偉大之處就是,提供了讀寫鎖分離
,分離的好處就是可以讓讀鎖共享,就是多個線程可以共享讀鎖,讀讀共享以及寫寫互斥以及讀寫互斥,是這個鎖的主要特點。下面是這個類的實現源碼結構圖:
上圖有個AQS,這個是AbstractQueuedSynchronizer類的縮寫,這個類是lock實現的重點,有興趣的可以研究一下源碼,Sync是AQS的實現,在ReentrantLock以及ReentrantReadWriteLock
類中,都有具體的實現,而FairSync和NonFairSync就是所謂的公平鎖以及非公平鎖