java.util.concurrent,并发编程常用的工具类:包含了线程池、阻塞队列、计时器、同步器、并发集合等 作者:Dong Lea。

Lock

Lock 本质上是一个接口,它定义了释放锁和获得锁的抽象方法,定义成接口就意
味着它定义了锁的一个标准规范,也同时意味着锁的不同实现。
Lock 有很多的锁的实现,但是直观的实现是 ReentrantLock 重入锁。
1.ReentrantLock:
表示重入锁,表示支持重新进入的锁,它是唯一一个实现了 Lock 接口的类。重入锁指的是线程在获得锁之后,再次获取该锁不需要阻塞,而是直接关联一次计数器增加重入次数。

重入锁的设计目的是避免线程的死锁。
形成死锁的原因:
调用 demo 方法获得了当前的对象锁,然后在这个方法中再去调用demo2,demo2 中的存在同一个实例锁,这个时候当前线程会因为无法获得demo2 的对象锁而阻塞,就会产生死锁。

案例:
public class ReentrantDemo{
	 public synchronized void demo(){
		 System.out.println("begin:demo");
		 demo2();
	 }
	 public void demo2(){
		 System.out.println("begin:demo1");
		 synchronized (this){
		 }
	 }
	 public static void main(String[] args) {
		 ReentrantDemo rd=new ReentrantDemo();
		 new Thread(rd::demo).start();
	 }
}

ReentrantLock的使用案例:

public class AtomicDemo {
    private static int count=0;
    static Lock lock=new ReentrantLock();
    public static void inc(){
        lock.lock();
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        count++;
        lock.unlock();
    }
    public static void main(String[] args) throws
            InterruptedException {
        for(int i=0;i<1000;i++){
            new Thread(()->{AtomicDemo.inc();}).start();;
        }
        Thread.sleep(3000);
        System.out.println("result:"+count);
    }
}

ReentrantReadWriteLock
我们以前理解的锁,基本都是排他锁,也就是这些锁在同一时刻只允许一个线程进
行访问,而读写锁在同一时刻可以允许多个读线程访问,但是在写线程访问时,所有的读线程和其他写线程都会被阻塞。也就是说只维护读锁和写锁。
读写锁的性能都会比排它锁好,因为大多数场景读是多于写的。在读多于写的情况下,读写锁能够提供比排它锁更好的并发性和吞吐量。

**读写锁案例**
public class LockDemo {
	 static Map<String,Object> cacheMap=new HashMap<>();
	 static ReentrantReadWriteLock rwl=new ReentrantReadWriteLock();
	 static Lock read=rwl.readLock();
	 static Lock write=rwl.writeLock();
	 public static final Object get(String key) {
		 System.out.println("开始读取数据");
		 read.lock(); //读锁
		 try {
		 	return cacheMap.get(key);
		 }finally {
			read.unlock();
		 }
	 }
	 public static final Object put(String key,Object value){
		 write.lock();
		 System.out.println("开始写数据");
		 try{
		 	return cacheMap.put(key,value);
		 }finally {
		 	write.unlock();
		 }
		 } 
 }