咱们知道,锁是用来控制多个线程访问共享资源的方式,通常来讲,一个锁可以防止多个线程同时访问共享资源,在Lock接口出现以前,Java应用程序只能依靠synchronized关键字来实现同步锁的功能,在java5之后,增长了JUC
java
的并发包且提供了Lock接口用来实现锁的功能,它提供了与synchroinzed关键字相似的同步功能,只是它比synchronized更灵活,可以显示的获取和释放锁。面试
Lock的初步使用缓存
Lock是一个接口安全
两个核心的方法lock和unlock。有6个实现类并发
ReentrantLockide
重入锁,表示支持从新进入的锁,也就是说,若是当前线程t1经过调用lock方法获取了锁以后,再次调用lock,是不会再阻塞去获取锁的,直接增长重试次数就好了。性能
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @auther: tianweichang * @date: 2018/9/5 06 * @Description: */ public class AtomicDemo { private static int count=0; static Lock lock=new ReentrantLock(); private static void inc(){ lock.lock(); try { Thread.sleep(1); System.out.println(count); }catch (InterruptedException e){ e.printStackTrace(); } count++; lock.unlock(); } public static void main(String[] args) { for (int i=0;i<1000;i++){ new Thread(()->{AtomicDemo.inc();}).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("count="+count); } }
ReentrantReadWriteLockspa
咱们之前理解的锁,基本都是排他锁,也就是这些锁在同一时刻只容许一个线程进行访问,而读写所在同一时刻能够容许多个线程访问,可是在写线程访问时,全部的读线程和其余写线程都会被阻塞。读写锁维护了一对锁,一个读锁、一个写锁; 通常状况下,读写锁的性能都会比排它锁好,由于大多数场景读是多于写的。在读多于写的状况下,读写锁可以提供比排它锁更好的并发性和吞吐量线程
import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @auther: tianweichang * @date: 2018/9/5 06 * @Description: */ 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(); } } }
在这个案例中,经过hashmap来模拟了一个内存缓存,而后使用读写所来保证这个内存缓存的线程安全性。当执行读操做的时候,须要获取读锁,在并发访问的时候,读锁不会被阻塞,由于读操做不会影响执行结果。在执行写操做是,线程必需要获取写锁,当已经有线程持有写锁的状况下,当前线程会被阻塞,只有当写锁释放之后,其余读写操做才能继续执行。使用读写锁提高读操做的并发性,也保证每次写操做对全部的读写操做的可见性orm
读锁与读锁能够共享
读锁与写锁不能够共享(排他)
写锁与写锁不能够共享(排他)
Lock和synchronized的简单对比
经过咱们对Lock的使用以及对synchronized的了解,基本上能够对比出这两种锁的区别了。由于这个也是在面试过程当中比较常见的问题
从层次上,一个是关键字、一个是类, 这是最直观的差别
从使用上,lock具有更大的灵活性,能够控制锁的释放和获取; 而synchronized的锁的释放是被动的,当出现异常或者同步代码块执行完之后,才会释放锁
lock能够判断锁的状态、而synchronized没法作到
lock能够实现公平锁、非公平锁; 而synchronized只有非公平锁