咱們知道,鎖是用來控制多個線程訪問共享資源的方式,通常來講,一個鎖可以防止多個線程同時訪問共享資源,在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只有非公平鎖