ArrayBlockingQueue
基于数组的有界的阻塞队列,其实现线程同步的方式为ReentrantLock 和两个条件,存取用了一把锁,其在线程池中常 见,下面贴出其put
- public void put(E e) throws InterruptedException {
- if (e == null) throw new NullPointerException();
- final E[] items = this.items;
- final ReentrantLock lock = this.lock;
- //由于需要支持方法可中断行为,这里使用可中断的锁操作。
- lock.lockInterruptibly();
- try {
- try {
- while (count == items.length)
- notFull.await();//队列满时,在notFull条件上等待。
- } catch (InterruptedException ie) {
- notFull.signal(); // 被中断后,唤醒其他等待notFull条件的线程。
- throw ie;
- }
- insert(e);
- } finally {
- lock.unlock();
- }
- }
- /**
- * Circularly increment i.
- */
- final int inc(int i) {
- return (++i == items.length)? 0 : i;
- }
- /**
- * 在内部数组的putIndex位置插入元素,调整putIndex和count,然后唤醒notEmpty条件上等待的线程。
- * 本方法只有在持有锁的情况下才会被调用。
- */
- private void insert(E x) {
- items[putIndex] = x;
- putIndex = inc(putIndex);
- ++count;
- notEmpty.signal();
- }
ConcurrentHashMap
实现了线程安全的Hashmap,在功能上和Hashtable一致,但性能要高出许多,因为Hashtable对所有方法做了同步处理,而这个类因为实现了分段锁,所以有更好的性能和伸缩性(即承受并发的能力),ConcurrentHashMap内部包含一个segment数组,每一个segment都是一个锁的子类,其下为哈希表
存取策略不同
put时
三次hash找到位置,然后上锁,put,解锁
get时
由于不需要对数据修改,所以理论上不用上锁,但是,当get同时另有线程put时,一是put其他元素,和我们无关,直接return,二是正好put我们get的元素时,我们就再加锁读一次
ConcurrentLinkedQueue
当前常用的多线程同步机制有三种:volatile、CAS、重量级锁,CLQ使用CAS实现非阻塞算法
CopyOnWrite
lock
newarray = arrayscopyof(oldarray,len+1)
set(newarray)
unlock