标签:bar locking ons dwr barrier its interrupt code 好的
1)与synchronized的区别是,它需要手动申请锁与解锁,在 finally 块中释放锁,而synchronized是JVM自动处理的。可控性上ReentrantLock更强。
由于ReentrantLock是重入锁,所以可以反复得到相同的一把锁,它有一个与锁相关的获取计数器,如果拥有锁的某个线程再次得到锁,那么获取计数器就加1,然后锁需要被释放两次才能获得真正释放(重入锁)。
注:synchronized 也是可重入的,当线程进入由线程已经拥有的监控器保护的 synchronized 块,就允许线程继续进行,当线程退出第二个(或者后续) synchronized 块的时候,不释放锁,只有线程退出它进入的监控器保护的第一个synchronized 块时,才释放锁,例如:
在带有锁的方法1里面调用了带有锁的方法2,这时在方法1获得的锁还是没有释放的,其它线程还是访问不了方法1,即使方法2结束了,直至方法1的锁释放,锁才会真正释放。假如有多个线程同时来调用方法1,那输出结果还是按顺序输出:1,2,1,2...
2)还有与synchronized不同的是,ReentrantLock对中断是有响应的。普通的lock.lock()是不能响应中断的,lock.lockInterruptibly()能够响应中断。
3)可限时,超时不能获得锁,就返回false,不会永久等待构成死锁,使用lock.tryLock(long timeout, TimeUnit unit)来实现可限时锁,参数为时间和单位。无法获得后就直接退出了。
Condition与ReentrantLock的关系就类似于synchronized与Object.wait()/signal()
await()方法会使当前线程等待,同时释放当前锁,当其他线程中使用signal()时或者signalAll()方法时,线 程会重新获得锁并继续执行。或者当线程被中断时,也能跳出等待。这和Object.wait()方法很相似。
awaitUninterruptibly()方法与await()方法基本相同,但是它并不会再等待过程中响应中断。 singal()方法用于唤醒一个在等待中的线程。相对的singalAll()方法会唤醒所有在等待中的线程。这和Obejct.notify()方法很类似。
对于锁来说,它是互斥的排他的。意思就是,只要我获得了锁,没人能再获得了。
而对于Semaphore来说,它允许多个线程同时进入临界区。可以认为它是一个共享锁,但是共享的额度是有限制的,额度用完了,其他没有拿到额度的线程还是要阻塞在临界区外。当额度为1时,就相等于lock。
常用方法有:
semaphore.acquire();//申请许可,当然一个线程也可以一次申请多个许可acquire(
int
permits)
semaphore.release();//释放许可
ReadWriteLock是区分功能的锁。读和写是两种不同的功能,读-读不互斥,读-写互斥,写-写互斥。
这样的设计是并发量提高了,又保证了数据安全。
使用方式是:
private
static
ReentrantReadWriteLock readWriteLock=
new
ReentrantReadWriteLock();
private
static
Lock readLock = readWriteLock.readLock();
private
static
Lock writeLock = readWriteLock.writeLock();
倒数计时器,等待所有检查线程全部完工后,再执行。每个任务完成后调用countDown(),计数器就会减1,当计数为0的时候,await()阻塞后面的方法会继续执行。
和CountDownLatch相似,也是等待某些线程都做完以后再执行。与CountDownLatch区别在于这个计数器可以反复使用。比如,假设我们将计数器设置为10。那么凑齐第一批1 0个线程后,计数器就会归零,然后接着凑齐下一批10个线程。并且每次完成一批线程后会触发一个动作
CyclicBarrier(
int
parties, Runnable barrierAction)//
barrierAction就是当计数器一次计数完成后,系统会执行的动作
也是通过await()来阻塞主线程等待任务全部完成
我们知道HashMap不是一个线程安全的容器,最简单的方式使HashMap变成线程安全就是使用Collections.synchronizedMap,它是对HashMap的一个包装,如:
Collections.synchronizedMap(
new
HashMap())
同理对于List,Set也提供了相似方法。
但是这种方式只适合于并发量比较小的情况,它会将HashMap包装在里面,然后将HashMap的每个操作都加上synchronized。
下面来看下ConcurrentHashMap是如何实现的:
在 ConcurrentHashMap内部有一个Segment段,它将大的HashMap切分成若干个段(小的HashMap),然后让数据在每一段上Hash,这样多个线程在不同段上的Hash操作一定是线程安全的,所以只需要同步同一个段上的线程就可以了,这样实现了锁的分离,大大增加了并发量。
在使用ConcurrentHashMap.size时会比较麻烦,因为它要统计每个段的数据和,在这个时候,要把每一个段都加上锁,然后再做数据统计。这个就是把锁分离后的小小弊端,但是size方法应该是不会被高频率调用的方法。
BlockingQueue不是一个高性能的容器。但是它是一个非常好的共享数据的容器。是典型的生产者和消费者的实现。
标签:bar locking ons dwr barrier its interrupt code 好的
原文地址:http://www.cnblogs.com/ptw-share/p/6681353.html