线程并发学习—-核心概念(转载)
线程并发学习—-线程阻塞(sleep、wait、notifyAll、notify、join)
线程并发学习—-线程阻塞(synchronized)
线程并发学习—-线程阻塞(lock)
线程并发学习—-Thread、Runnable、Callable
线程并发学习—-队列(Queue)
线程并发学习—-JUC工具类
spring学习—-线程池
java中一些锁概念整理(转载)
简介
常用工具类CountDownLatch、CyclicBarrier、Semaphore;
- CountDownLatch通过AQS实现
- CyclicBarrier通过ReentrantLock
- Semaphore实现原理与ReentrantLock类似,通过内部类Sync、NonfairSync、FairSync,不过其是对一组资源的限制
分析
- CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同:
- CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行;
- 而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;
另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的。
Semaphore其实和锁有点类似,它一般用于控制对某组资源的访问权限。
CountDownLatch
方法
- await() 调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
- await(long timeout, TimeUnit unit) 和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
- countDown() 将count值减1
源码
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
分析
从上面代码可以看出,CountDownLatch初始化设置一个state值(等待线程数),调用await方法判断state是否为0,如果是0,不阻塞,否则进入等待队列阻塞;每次调用countDown方法将state减1
示例
public class CountDownLatchDemo {
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(1);
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
Thread.sleep(1000);
System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
try {
System.out.println("等待1个子线程执行完毕...");
latch.await();
System.out.println("1个子线程已经执行完毕");
System.out.println("继续执行主线程");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
CyclicBarrier
方法
await() 调用后线程就处于barrier了,等待一组线程都到达barrier后全部同时执行
源码
private final ReentrantLock lock = new ReentrantLock();
分析
从上可以看出CyclicBarrier通过ReentrantLock实现
Semaphore
方法
阻塞
- acquire() 获取一个许可
- acquire(int permits) 获取permits个许可
- release() 释放一个许可
- release(int permits) 释放permits个许可
非阻塞
- tryAcquire() 尝试获取一个许可,若获取成功,则立即返回true,若获取失败,则立即返回false
- tryAcquire(long timeout, TimeUnit
unit)尝试获取一个许可,若在指定的时间内获取成功,则立即返回true,否则则立即返回false - tryAcquire(int permits)
尝试获取permits个许可,若获取成功,则立即返回true,若获取失败,则立即返回false - tryAcquire(int permits, long timeout, TimeUnit unit)
尝试获取permits个许可,若在指定的时间内获取成功,则立即返回true,否则则立即返回false
分析
从代码可以看出,Semaphore与ReentrantLock实现非常相似,区别在于Semaphore初始化的时候是可以锁定一组资源