JavaLock(同步器,例子)

一个例子

在上述对同步器AbstractQueuedSynchronizer进行了实现层面的分析之后,我们通过一个例子来加深对同步器的理解:

设计一个同步工具,该工具在同一时刻,只能有两个线程能够并行访问,超过限制的其他线程进入阻塞状态。

对于这个需求,可以利用同步器完成一个这样的设定,定义一个初始状态,为2,一个线程进行获取那么减1,一个线程释放那么加1,状态正确的范围在[0,1,2]三个之间,当在0时,代表再有新的线程对资源进行获取时只能进入阻塞状态(注意在任何时候进行状态变更的时候均需要以CAS作为原子性保障)。

public class TwinsLock implements Lock {
	private static final Sync sync = new Sync();
	private static final class Sync extends AbstractQueuedSynchronizer {
		private static final long serialVersionUID = -7889272986162341211L;
		{
			setState(2);
		}
		
		protected boolean tryAcquire(int arg) {
			if (arg != 1) {
				return false;
			}
			int currentStats = getState();
			if (currentStats <= 0) {
				return false;
			}
			if (compareAndSetState(currentStats, currentStats - 1)) {
				setExclusiveOwnerThread(Thread.currentThread());
				return true;
			}
			return false;
		}

		protected boolean tryRelease(int arg) {
			if (arg != 1) {
				return false;
			}
			for(;;) {
				int currentStats = getState();
				if (compareAndSetState(currentStats, currentStats + 1)) {
				setExclusiveOwnerThread(null);
				return true;
				}
			}
		}
	
		protected boolean isHeldExclusively() {
	    		return getState() < 2;
		}
    	}

	public void lock() {
		sync.acquire(1);
    	}

    	public void lockInterruptibly() throws InterruptedException {
		sync.acquireInterruptibly(1);
    	}

	public boolean tryLock() {
		return sync.tryAcquire(1);
    	}

    	public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
		return sync.tryAcquireNanos(1, unit.toNanos(time));
    	}

    	public void unlock() {
		sync.release(1);
    	}

}

 

这里我们编写一个测试来验证TwinsLock是否能够正常工作并达到预期。

public class TwinsLockTest {

	@Test
	public void test() {
		final Lock lock = new TwinsLock();

		class Worker extends Thread {
			public void run() {
				while (true) {
					lock.lock();

					try {
						Thread.sleep(1000L);
				System.out.println(Thread.currentThread());
						Thread.sleep(1000L);
					} catch (Exception ex) {

					} finally {
						lock.unlock();
					}
				}
			}
		}

		for (int i = 0; i < 10; i++) {
			Worker w = new Worker();
			w.start();
		}

		new Thread() {
			public void run() {
				while (true) {

					try {
						Thread.sleep(200L);
						System.out.println();
					} catch (Exception ex) {

					}
				}
			}
		}.start();

		try {
			Thread.sleep(20000L);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

 

上述测试用例的逻辑主要包括:

1. 打印线程

Worker在两次睡眠之间打印自身线程,如果一个时刻只能有两个线程同时访问,那么打印出来的内容将是成对出现。

2. 分隔线程

不停的打印换行,能让Worker的输出看起来更加直观。

 

该测试的结果是在一个时刻,仅有两个线程能够获得到锁,并完成打印,而表象就是打印的内容成对出现。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值