多執行緒學習七——實現獨佔鎖
阿新 • • 發佈:2018-12-09
獨佔鎖:有且只有一個執行緒能持有該鎖,而且獲得鎖的執行緒也只能獲得一次,不能獲得多次
package day1;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
public class MutexLock implements Lock {
// 靜態內部類,自定義同步器
private static class Sync extends AbstractQueuedSynchronizer {
/**
*
*/
private static final long serialVersionUID = 1L;
// 是否處於佔用狀態
protected boolean isHeldExclusively() {
return getState() == 1;
}
// 當狀態為0的時候獲取鎖
public boolean tryAcquire(int acquires) {
//獨佔鎖實現的關鍵,只有鎖沒有被佔時才可能獲得鎖
if (compareAndSetState(0, 1)) {
//獲得鎖成功,設定擁有鎖的執行緒為當前執行緒
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
// 釋放鎖,將狀態設定為0
protected boolean tryRelease(int releases) {
if (getState() == 0)
throw new IllegalMonitorStateException();
setExclusiveOwnerThread(null);
setState(0);
return true;
}
// 返回一個Condition,每個condition都包含了一個condition佇列
Condition newCondition() {
return new ConditionObject();
}
}
// 僅需要將操作代理到Sync上即可
private final Sync sync = new Sync();
public void lock() {
sync.acquire(1);
}
public boolean tryLock() {
return sync.tryAcquire(1);
}
public void unlock() {
sync.release(1);
}
public Condition newCondition() {
return sync.newCondition();
}
public boolean isLocked() {
return sync.isHeldExclusively();
}
public boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
}
如果是一個回撥方法的話,會形成死鎖,如:
package day1;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MutexLockTest {
private static MutexLock lock = new MutexLock();
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(new Thread1());
executor.shutdown();
}
static class Thread1 implements Runnable {
@Override
public void run() {
try {
lock.lock();
lock.lock();
System.out.println(sumNum(1,100));
} finally {
lock.unlock();
}
}
int sum = 0;
public int sumNum(int start,int end) {
if(start <=end) {
sum = sum+start;
sumNum(start+1,end);
}
return sum;
}
}
}