自定义独占锁只需要定义一个非公开的内部类继承AbstractQueuedSynchronizer类重写tryAcquire和tryRelease就可以了。
package multi;
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 MyLock implements Lock{
private final Sync sync;
public MyLock(){
sync = new Sync();
}
private class Sync extends AbstractQueuedSynchronizer{
private static final long serialVersionUID = 4206028266355265870L;
protected boolean tryAcquire(int arg) {
int state = getState();
Thread currentThread = Thread.currentThread();
if(state == 0){
if(compareAndSetState(state, arg)){
setExclusiveOwnerThread(currentThread);
return true;
}
}
if(currentThread == getExclusiveOwnerThread()){
state = getState();
setState(state + 1);
return true;
}
return false;
}
protected boolean tryRelease(int arg) {
if(Thread.currentThread() != getExclusiveOwnerThread()){
throw new RuntimeException();
}
int state = getState() - arg;
if(state < 0 ){
throw new RuntimeException();
}
boolean flag = false;
if(state == 0){
// 先设定当前线程为空后,再设定state值
setExclusiveOwnerThread(null);
flag = true;
}
setState(state);
return flag;
}
protected Condition newCondition() {
return new ConditionObject();
}
}
@Override
public void lock() {
sync.acquire(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
return sync.tryAcquire(1);
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(time));
}
@Override
public void unlock() {
sync.release(1);
}
@Override
public Condition newCondition() {
return sync.newCondition();
}
}
测试代码:
package multi;
public class Main {
private int count;
private MyLock lock = new MyLock();
private void incr(){
lock.lock();
try{
count++;
lock.lock();
try{
count++;
}finally{
lock.unlock();
}
}finally{
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Main main = new Main();
Thread thread1 = new Thread(new Runnable(){
@Override
public void run() {
for(int i = 0;i < 100000;i++){
main.incr();
}
}
},"thread1");
Thread thread2 = new Thread(new Runnable(){
@Override
public void run() {
for(int i = 0;i < 100000;i++){
main.incr();
}
}
},"thread2");
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(main.count);
}
}