10,使用CAS和AQS实现自定义锁
java并发编程中,锁无处不在。java的容器框架中,也提供了满足各种场景的锁。但是,有一个共性就是,他们都是基于AbstractQueuedSynchronizer(AQS)。
下面,使用CAS和AQS实现一个自己的锁!
自定义独占锁只需要定义一个非公开的内部类继承AbstractQueuedSynchronizer类。AQS提供了一个模板,根据模板,重写方法即可(看见Shared结尾的方法,属于共享模式)。
public class MyLock implements Lock {
/**
* 默认信号量
*/
private static final int DEF_STATE = 1;
private class Sync extends AbstractQueuedSynchronizer{
//获取锁(独占模式)
@Override
protected boolean tryAcquire(int arg) {
int state = getState();
if(state == 0){
//能够获取到锁,通过CAS改变state的值
if(compareAndSetState(0, arg)){
//设置当前线程占有资源
setExclusiveOwnerThread(Thread.currentThread());
return true;
//判断是否是当前线程,如果是,则重入一次(重入性)
} else if(getExclusiveOwnerThread()==Thread.currentThread()){
setState(state + arg);
return true;
}
}
return false;
}
//释放锁(独占模式)
@Override
protected boolean tryRelease(int arg) {
int state = getState() - arg;
//判断释放后是否为0
if (state == 0) {
//设置新的state=0
setState(state);
//清除锁的持有线程标记
setExclusiveOwnerThread(null);
return true;
}
//由于是独占模式,每次修改setState,只会有一个线程修改state,不存在多线程安全问题
setState(state);
return false;
}
public Condition newConditionObjecct(){
return new ConditionObject();
}
}
private Sync sync = new Sync();
/**
* 获取锁
*/
@Override
public void lock() {
sync.acquire(DEF_STATE);
}
/**
* 中断的方式去获取锁
* @throws InterruptedException
*/
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(DEF_STATE);
}
/**
* 尝试去获取锁
* @return
*/
@Override
public boolean tryLock() {
return sync.tryAcquire(DEF_STATE);
}
/**
* 带有超时时间的尝试去获取锁
* @param time 自旋超时时间
* @param unit 时间帮助类
* @return
* @throws InterruptedException 中断异常
*/
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(DEF_STATE, unit.toNanos(time));
}
/**
* 释放锁
*/
@Override
public void unlock() {
//调用咱们自定义的tryRelease()方法
sync.release(DEF_STATE);
}
/**
* 获取条件对象
* @return
*/
@Override
public Condition newCondition() {
return sync.newConditionObjecct();
}
}
使用自定义的MyLock锁
public class MyLockDemo01 {
public static int m = 0;
private static MyLock lock = new MyLock();
public int addM(){
try {
lock.lock();
return m++;
} finally {
lock.unlock();
}
}
public static void main(String[] args){
MyLockDemo01 demo = new MyLockDemo01();
//初始化10个线程
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(() -> {
System.out.println("m:" + demo.addM());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
threads[i].start();
}
}
}
版权声明
非特殊说明,本文由Zender原创或收集发布,欢迎转载。
上一篇:9、AQS-CountDownLatch(共享锁) 下一篇:1,MySQL 索引
ZENDER

发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。