1、自定义锁代码
/*
核心:
1) 自定义可重入锁的类,实现 Lock 接口;
2) 重写 Lock 接口中所有的方法;
3) 自定义一个 私有内部类,并继承 AbstractQueuedSynchronizer;
4) 重写 tryAcquire 和 tryRelease 方法,以及新增一个获取 Condition 对象的方法。
自定义同步器在实现时只需要实现共享资源state的获取与释放方式即可,
至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等),AQS已经在顶层实现好了
下方代码主要参考 ReentrantLock 的实现,所以推荐了解一下 ReentrantLock。
*/
package com.example.aqs;
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 Integer semaphore = 1;
// 期望值
private final Integer expectValue = 0;
// 初始化自定义锁
private final Helper myLock = new Helper();
// 自定义 私有内部类
private class Helper extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire(int semaphore) {
int state = getState();
// 等于0代表当前没有线程获取锁
if (state == 0) {
// 使用CAS方式同步修改状态state
if (compareAndSetState(expectValue, semaphore)) {
setExclusiveOwnerThread(Thread.currentThread());
// true: 成功获取对象锁
return true;
}
return false;
}
// 如果有线程已经占用了锁
// 判断占用当前锁的线程是否为现在的线程
if (Thread.currentThread().equals(getExclusiveOwnerThread())) {
setState(getState() + semaphore);
return true;
}
return false;
}
@Override
protected boolean tryRelease(int semaphore) {
int state = getState() - semaphore;
if (state == 0) {
// Exclusive: 独占的
setExclusiveOwnerThread(null);
setState(state);
// 当前对象处于完全释放状态时,返回true;
// true: 如果此对象现在处于完全释放状态,那么任何等待的线程都可能尝试获取; false: 其他
return true;
}
setState(state);
// 当前对象处于未完全释放状态时,返回false;
return false;
}
public Condition newConditionObject() {
return new ConditionObject();
}
}
@Override
public void lock() {
myLock.acquire(semaphore);
}
@Override
public void lockInterruptibly() throws InterruptedException {
myLock.acquireInterruptibly(semaphore);
}
@Override
public boolean tryLock() {
return myLock.tryAcquire(semaphore);
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return myLock.tryAcquireNanos(semaphore, unit.toNanos(time));
}
@Override
public void unlock() {
myLock.release(semaphore);
}
@Override
public Condition newCondition() {
return myLock.newConditionObject();
}
}
2、测试是否能保证数据的一致性
package com.example.aqs;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 测试自定义锁
*/
public class MyLockTest {
private Integer m = 0;
// 自定义的锁对象
private MyLock myLock = new MyLock();
// JUC下的锁对象
// private Lock lock = new ReentrantLock();
private void increment() {
myLock.lock();
System.out.println(++m);
myLock.unlock();
}
public static void main(String[] args) {
MyLockTest myLockTest = new MyLockTest();
for (int i = 0; i < 100; i++) {
new Thread(myLockTest::increment).start();
}
}
}
/*
结果:
1
2
3
......
100
*/
3、测试可重入性
package com.example.aqs;
import java.util.concurrent.locks.Lock;
public class MyLockReentrantTest {
private final MyLock myLock = new MyLock();
private void method1() {
myLock.lock();
System.out.println("Nice to meet to you, I'm method1!");
method2();
myLock.unlock();
}
private void method2() {
myLock.lock();
System.out.println("Nice to meet to you, too! I'm method2!");
myLock.unlock();
}
public static void main(String[] args) {
MyLockReentrantTest myLockReentrantTest = new MyLockReentrantTest();
new Thread(myLockReentrantTest::method1).start();
}
}
/*
结果:
Nice to meet to you, I'm method1!
Nice to meet to you, too! I'm method2!
*/