1)Lock与synchronized的区别:java
1)Lock显示地获取和释放锁: void lock(); // 获取锁。 void unlock(); // 释放锁。 2)能够非阻塞的获取锁: boolean tryLock(); // 调用该方法后马上返回,若是能获取到锁则返回true,不然返回false; 3)能够中断地获取锁: void lockInterruptibly() throws InterruptedException; // 在锁的获取过程当中,若是获取锁的线程被中断,则抛出中断异常并返回。 4)能够超时地获取锁: boolean tryLock(long time, TimeUnit unit) throws InterruptedException; // 在time时间内,获取到锁返回true,若是获取锁的线程被中断则返回false;超出time时间,返回false。 5)Condition newCondition(); Condition:java.util.concurrent.locks.Condition 1)每一个Condition对象都包含着一个等待队列,该队列是Condition对象实现等待/通知功能的关键。 2)等待队列是一个FIFO的队列,在队列中的每一个节点都包含了一个线程引用,该线程就是在Condition对象上等待的线程。 3)若是一个线程调用了Condition.await()方法,那么该线程将会释放锁,而且构形成节点加入等待队列并进入等待状态。 4)事实上,同步队列(获取Lock排队)和等待队列(获取Condition排队)中节点的类型都是同步器的静态内部类AbstractQueuedSynchronizer.Node 5)注意:在condition.await()方法调用以前,必须先用lock.lock()方法获取到锁。 6)多路通知功能: 在一个Lock对象里面建立多个Condition实例,线程对象能够注册在指定的Condition中,从而能够有选择地进行线程通知。能够先对线程进行分组,而后再唤醒指定组中的线程。 实现:ReentrantLock、ReentrantReadWriteLock、CountDownLatch
2)ReentrantLock(重入锁):并发
重入: 1)重入是指任意线程在获取到锁以后可以再次获取该锁而不会被阻塞。 2)在调用lock()方法时,已经获取到锁的线程,可以再次调用lock()方法获取锁而不被阻塞。 重入的过程: 1)线程再次获取锁:锁须要去识别获取锁的线程是否为当前占据锁的线程,若是是,则再次成功获取。 2)锁的最终释放: 1>获取锁时须要进行计数自增,计数表示当前锁被重复获取的次数,而锁被释放时,计数自减,当计数等于0时表示锁已经成功释放。 2>线程重复n次获取了锁,随后在释放n次该锁后,其它线程可以获取到该锁。 支持获取锁时的公平性和非公平性选择: 1)公平锁保证了锁的获取按照FIFO原则,其代价是须要进行大量的线程切换。 2)非公平锁虽然可能形成线程“饥饿”,可是极少的线程切换,保证了其更大的吞吐量。 ReentrantLock类中封装的AQS的同步状态表示锁被一个线程重复获取的次数。 举例: ------------------------------------------ 实现等待/通知的service类: import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class MessageService { private Lock lock = new ReentrantLock(); public Condition conditionA = lock.newCondition(); public Condition conditionB = lock.newCondition(); public void awaitA() { try { lock.lock(); System.out.println("start awaitA, time:" + System.currentTimeMillis() + " ThreadName:" + Thread.currentThread().getName()); conditionA.await(); System.out.println("end awaitA, time:" + System.currentTimeMillis() + " ThreadName:" + Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void awaitB() { try { lock.lock(); System.out.println("start awaitB, time:" + System.currentTimeMillis() + " ThreadName:" + Thread.currentThread().getName()); conditionB.await(); System.out.println("end awaitB, time:" + System.currentTimeMillis() + " ThreadName:" + Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void signalAllforA() { try { lock.lock(); System.out.println("signalAllforA, time:" + System.currentTimeMillis() + " ThreadName:" + Thread.currentThread().getName()); conditionA.signalAll(); } finally { lock.unlock(); } } public void signalAllforB() { try { lock.lock(); System.out.println("signalAllforB, time:" + System.currentTimeMillis() + " ThreadName:" + Thread.currentThread().getName()); conditionB.signalAll(); } finally { lock.unlock(); } } } --------------------- 线程A public class ThreadA extends Thread{ private MessageService messageService; public ThreadA(MessageService messageService) { this.messageService = messageService; } [@Override](https://my.oschina.net/u/1162528) public void run() { this.messageService.awaitA(); } } --------------------- 线程B public class ThreadB extends Thread{ private MessageService messageService; public ThreadB(MessageService messageService) { this.messageService = messageService; } [@Override](https://my.oschina.net/u/1162528) public void run() { this.messageService.awaitB(); } } --------------------- 测试类: public class LockTest { public static void main(String[] args) { try { MessageService messageService = new MessageService(); ThreadA threadA = new ThreadA(messageService); threadA.setName("Thread-A"); threadA.start(); ThreadB threadB = new ThreadB(messageService); threadB.setName("Thread-B"); threadB.start(); Thread.sleep(5000); messageService.signalAllforA(); // 运行后,只有ThreadA被唤醒了 } catch (InterruptedException e) { e.printStackTrace(); } } } 结果: start awaitA, time:1497603307947 ThreadName:Thread-A start awaitB, time:1497603307947 ThreadName:Thread-B signalAllforA, time:1497603312947 ThreadName:main end awaitA, time:1497603312947 ThreadName:Thread-A ------------------------------------------
3)ReadWriteLock(读写锁):ide
概念:读写锁维护了一对锁,一个读锁和一个写锁,经过分离读锁和写锁,使得并发性相比通常的独占锁有了很大提高。 源码: package java.util.concurrent.locks; public interface ReadWriteLock { /** Returns the lock used for reading. */ Lock readLock(); /** Returns the lock used for writing. */ Lock writeLock(); } 说明: 1)读写锁在同一时刻能够容许多个读线程访问,可是在写线程访问时,其它的读线程和写线程均被阻塞。 2)若是当前线程获取了写锁或者写锁未被获取,则当前线程能够获取读锁。 3)若是当前线程在获取读锁时,写锁已被其余线程获取,则进入等待状态。 4)通常状况下,读写锁的性能都会比独占锁好,由于大多数场景读是多于写的。 5)在读多于写的状况下,读写锁可以提供比独占锁更好的并发性和吞吐量。 实现:ReentrantReadWriteLock 特色: 1)支持公平性选择 2)支持读锁和写锁的重入 3)支持锁降级: 1>锁降级的概念:先获取到写锁后,再获取到读锁,随后才释放写锁,最后只持有读锁的过程。 2>按照获取写锁、获取读锁、释放写锁的顺序进行操做,从而将写锁降级为读锁。 说明: 1)若是存在读锁,则写锁不能被获取,进入等待状态。 2)若是其它线程已经获取了写锁,则当前线程不能获取读锁,进入等待状态。 读写状态的设计: 在一个整型变量上维护多种状态,就须要“按位切割使用”这个变量,读写锁将变量切分红了两个部分,高16位表示读,低16位表示写。