本篇文章主要介绍了"JAVA并发编程--Semaphore、CountDownLatch、ReentrantLock、CyclicBarrier",主要涉及到方面的内容,对于Javajrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播感兴趣的同学可以参考一下:
Semaphore学习操作系统理论课的时候,教材上应该都会讲过信号量这种概念,java.util.concurrent.Semaphore类就是Java中这个概...
ExecutorService exec = Executors.newCachedThreadPool();
final CountDownLatch cdl = new CountDownLatch(3);
Runnable watingTasks = new Runnable() {
publicvoidrun() {
try {
System.out.println("there're 3 tasks here. if all tasks are finished, i will go home.");
System.out.println("working...");
cdl.await();
System.out.println("ok, i will go home now!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
exec.execute(watingTasks);
for (int i = 0; i < 3; i++) {
finalint tid = i;
Runnable semTask = new Runnable() {
publicvoidrun() {
try {
System.out.println("starting task " + tid + "...");
Thread.sleep((long) (Math.random() * 5000));
System.out.println("task " + tid + " finished");
cdl.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
exec.execute(semTask);
}
exec.shutdown();
和Semaphore类似,在使用AQS的实现上,主要有以下几点。
- state存储的是count计数变量
- Node采用的是SHARED模式
- countDown()调用tryReleaseShared使得计数减1
- await是调用tryAcquire,实际上就是判断state是否为0
ReentrantReadWriteLock
在高并发场景下,为了让任务执行更有效率,将读和写场景分离是有必要的。这是因为读和写在线程安全方面特点的不同,读不改变状态,多个线程是可以同时进行而没有问题的,而写与写、写与读之间都是需要互斥的。在java.util.concurrent中,ReentrantReadWriteLock这个类就是做这个事情的。
具体的使用就不举例了,直接分析下其实现。从类名上看ReentrantLock和ReentrantReadWriteLock就很相似,实现上也有相似的部分。ReentrantReadWriteLock中封装了ReadLock和WriteLock内部类,而ReentrantReadWriteLock、ReentrantReadWriteLock.ReadLock、ReentrantReadWriteLock.WriteLock中都有自己的Sync类属性,使用的是ReentrantReadWriteLock.Sync实现,而且对象关系上,ReadLock和WriteLock中的sync都是指向ReentrantReadWriteLock对象中的sync引用,即使用了同一个AQS同一套队列,只是将方法分离开来处理。
其中的要点:
- state同时存储r和w的个数
- WriteLock的锁操作类似ReentrantLock使用互斥节点
- 而readlock使用共享节点
- 读锁写锁的逻辑在各自的tryLock中,最终实现在ReadWriteLock的tryReadLock和tryWriteLock中
CyclicBarrier