示例:TwinsLock
设计一个同步工具:同一个时刻,只允许两个线程同时访问,超过两个线程访问将会被阻塞。
分析:首先,确定访问模式,TwinLock能够同一时刻支持多个线程同时访问,这明显是共享式访问。这需要同步器提供的acquireShared(int args)方法和Share相关的方法,同时要求重写tryAcquireShared(int args)等方法。
其次,定义资源数量,TwinsLock在同一时刻允许两个线程同时访问资源数量为2,这样可以设置初始状态为2,当一个线程进行获取,status减1,该线程释放,则status加1。状态的合法状态为0、1、2。
0:无锁可用,即已经有两个线程在访问资源,此时,再有其他线程获取同步状态,该线程只能被阻塞;
1:已加了一把锁,还剩一把;
2:无锁状态;还可以加两把锁;
实现代码如下:
public class TwinsLock implements Lock {
//静态内部类继承AQS
private static final class Sync extends AbstractQueuedSynchronizer {
//初始化同步状态为2,表示没有线程对资源进行访问
public Sync(int count) {
if (count < 0) {
throw new IllegalArgumentException("count must larger than zero.");
}
setState(2);
}
//获取同步状态:使用循环CAS操作来保证设置status的线程安全
@Override
protected int tryAcquireShared(int reduceCount) {
for(;;) {
int current = getState();
int newCount = current - reduceCount;
if (newCount < 0 || compareAndSetState(current, newCount)) {
return newCount; //结果<0,表示获取锁失败;=0,表示获取锁成功,但无剩余锁;=1,表示获取锁成功,还有剩余锁;
}
}
}
//释放同步状态:因为可能两个线程同时进行释放,需要使用循环CAS来保证安全
@Override
protected boolean tryReleaseShared(int returnCount) {
for(;;) {
int current = getState();
int newCount = current + returnCount;
if (compareAndSetState(current, newCount)) {
return true;
}
}
}
final ConditionObject newCondition() {
return new ConditionObject();
}
}
private final Sync sync = new Sync(2);
@Override
public void lock() {
sync.acquireShared(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
int count = sync.tryAcquireShared(1);
return count >= 0;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(time));
}
@Override
public void unlock() {
sync.releaseShared(1);
}
@Override
public Condition newCondition() {
return sync.newCondition();
}
}
测试
public class TwinsLockExample {
public static void main(String[] args) {
final Lock lock = new TwinsLock();
class Worker extends Thread {
@Override
public void run() {
while (true) {
lock.lock();
try {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1500);
} catch (InterruptedException e) {
System.out.println("interruptException!");
} finally {
lock.unlock();
break;
}
}
}
}
//启动10个线程
for (int i = 0; i < 10; i++) {
Worker worker = new Worker();
worker.setDaemon(true);
worker.start();
}
//每间隔一秒钟打印一个空行.
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println();
}
}
}
//输出如下
Thread-0
Thread-1
Thread-2
Thread-3
Thread-4
Thread-5
Thread-6
Thread-7
Thread-8
Thread-9
Last updated