基础:需要熟悉JUC工具包以及底层的cas原理和AQS
接下来我们正入主题
第一种最简单的方法,使用工具类来实现简单的同步
我们可以使用AtomicReference来操作当前,当然也可以使用semaphore,阻塞队列等,这样可以实现简单的锁,达到同步的效果。
public class AbleLock {
//新建一个原子引用类,负责操作当前线程
AtomicReference<Thread> reference=new AtomicReference<Thread>();
Thread thread=null;
public void lock() {
//获取当前的线程,如果是空的话,则进行cas操作
thread = Thread.currentThread();
if (reference.get() == null) {
reference.compareAndSet(null, thread);
}
}
public void unlock(){
//这里没有使用cas设置为null,原因是刚开始是很多线程同时在争抢,
//而拿到资源的线程只有一个,所以不必使用cas操作
reference.set(null);
}
}
接下来我们测试一下
public class TestLock {
int count=0;
AbleLock lock=new AbleLock();
public void add() {
lock.lock();
count++;
lock.unlock();
}
public int getCount(){
return count;
}
public static void main(String[] args) throws InterruptedException {
TestLock testLock=new TestLock();
for(int i=0;i<2000;i++){
Thread thread=new Thread(()->{
for(int j=0;j<500;j++){
testLock.add();
}
});
thread.start();
//先让其他的线程执行,最后主线程再输出count的值
thread.join();
}
System.out.println("count的值是"+testLock.getCount());
}
}
可以看出我们的结果已经达到了,但是这样的锁功能没有那么强大,只能实现简单的同步,不可重入,太多缺陷
第二种就是通过实现lock接口,定义一个内部类,通过继承AQS(AbstractQueuedSynchronizer)类达到排它锁,这里涉及到了模板设计模式
内部类继承AQS后,需要重写这几个方法
isHeldExclusively()
tryAcquire(int arg)
tryRelease(int arg)
public class SelfLock implements Lock {
private static class Sync extends AbstractQueuedSynchronizer{
//state 表示是否处于占用,1为占用,0为没有
//当前锁是否处于占用
@Override
protected boolean isHeldExclusively() {
return getState()==1;
}
@Override
protected boolean tryAcquire(int arg) {
if(compareAndSetState(0,1)){
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
@Override
protected boolean tryRelease(int arg) {
if(getState()==0){
throw new UnsupportedOperationException();
}
setExclusiveOwnerThread(null);
setState(0);
return true;
}
public Condition newCondition() {
return new ConditionObject();
}
}
private Sync sync=new Sync();
@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();
}
}
这样也就实现了锁的效果