6 Java多線程:鎖與AQS(下)( 二 )

然后再運行測試:
/** * 實現Lock接口方法并運行排他鎖測試 * * @author 湘王 */public class MyExclusiveLockTester {// 用自定義AQS獨占鎖實現private Lock lock = new MyExclusiveLock();private int value;public int accmulator() {lock.lock();try {++value;} finally {lock.unlock();}return value;}public static void main(String[] args) throws InterruptedException {MyExclusiveLockTester test = new MyExclusiveLockTester();for (int i = 0; i < 5; i++) {new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 5; i++) {System.out.println(test.accmulator());}}}).start();}}}可以看到 , 結果無論怎么樣都不會再重復了 。
這個只是簡單的累加,接下來用AQS來實現一個實際的生活場景 。比如周末帶女票或男票去步行街吃飯,這時候人特別多,需要搖號,而且一次只能進去三張號(不按人頭算 , 按叫到的號來算),該怎么實現呢?
可以順著這個思路:搖號機雖有很多號,但它本質上是個共享資源,很多人可以共享 , 但是每次共享的數量有限 。這其實就是個可以指定數量的共享鎖而已 。
既然有了思路,那接下來就好辦了 。
/** * 利用AQS實現自定義共享鎖 * * @author 湘王 */public class MyShareLock implements Lock {@Overridepublic void lock() {}@Overridepublic void lockInterruptibly() throws InterruptedException {}@Overridepublic boolean tryLock() {return false;}@Overridepublic boolean tryLock(long time, TimeUnit unit) throws InterruptedException {return false;}@Overridepublic void unlock() {}@Overridepublic Condition newCondition() {return null;}}還是一樣實現Lock接口,但這次是用AQS實現共享鎖 。
/** * 內部類繼承AQS實現共享鎖 * */private static class SyncHelper extends AbstractQueuedSynchronizer {private static final long serialVersionUID = -7357716912664213942L;/*** count表示允許幾個線程能同時獲得鎖*/public SyncHelper(int count) {if (count <= 0) {throw new IllegalArgumentException("鎖資源數量必須大于0");}// 設置資源總數setState(count);}/*** 一次允許多少個線程進來,允許數量的線程都能拿到鎖 , 其他的線程進入隊列*/@Overrideprotected int tryAcquireShared(int acquires) {// 自旋for (;;) {int state = getState();int remain = state - acquires;// 判斷剩余鎖資源是否已小于0或者CAS執行是否成功if (remain < 0 || compareAndSetState(state, remain)) {return remain;}}}/*** 鎖資源的獲取和釋放要一一對應*/@Overrideprotected boolean tryReleaseShared(int releases) {// 自旋for (;;) {// 獲取當前stateint current = getState();// 釋放狀態state增加releasesint next = current + releases;if (next < current) {// 溢出throw new Error("Maximum permit count exceeded");}// 通過CAS更新state的值// 這里不能用setState()if (compareAndSetState(current, next)) {return true;}}}protected Condition newCondition() {return new ConditionObject();}}然后再來改造之前實現的接口:
/** * 利用AQS實現自定義共享鎖 * * @author 湘王 */public class MyShareLock implements Lock {public static int count;private final SyncHelper synchepler = new SyncHelper(count);@Overridepublic void lock() {synchepler.acquireShared(1);}@Overridepublic void lockInterruptibly() throws InterruptedException {synchepler.acquireSharedInterruptibly(1);}@Overridepublic boolean tryLock() {return synchepler.tryAcquireShared(1) > 0;}@Overridepublic boolean tryLock(long time, TimeUnit unit) throws InterruptedException {return synchepler.tryAcquireSharedNanos(1, unit.toNanos(time));}@Overridepublic void unlock() {synchepler.releaseShared(1);}@Overridepublic Condition newCondition() {return synchepler.newCondition();}/*** 內部類繼承AQS實現共享鎖**/private static class SyncHelper extends AbstractQueuedSynchronizer {private static final long serialVersionUID = -7357716912664213942L;/*** count表示允許幾個線程能同時獲得鎖*/public SyncHelper(int count) {if (count <= 0) {throw new IllegalArgumentException("鎖資源數量必須大于0");}// 設置資源總數setState(count);}/*** 一次允許多少個線程進來,允許數量的線程都能拿到鎖,其他的線程進入隊列*/@Overrideprotected int tryAcquireShared(int acquires) {// 自旋for (;;) {int state = getState();int remain = state - acquires;// 判斷剩余鎖資源是否已小于0或者CAS執行是否成功if (remain < 0 || compareAndSetState(state, remain)) {return remain;}}}/*** 鎖資源的獲取和釋放要一一對應*/@Overrideprotected boolean tryReleaseShared(int releases) {// 自旋for (;;) {// 獲取當前stateint current = getState();// 釋放狀態state增加releasesint next = current + releases;if (next < current) {// 溢出throw new Error("Maximum permit count exceeded");}// 通過CAS更新state的值// 這里不能用setState()if (compareAndSetState(current, next)) {return true;}}}protected Condition newCondition() {return new ConditionObject();}}}

推薦閱讀