初識同步鎖

咱們知道,鎖是用來控制多個線程訪問共享資源的方式,通常來講,一個鎖可以防止多個線程同時訪問共享資源,在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的瞭解,基本上能夠對比出這兩種鎖的區別了。由於這個也是在面試過程當中比較常見的問題

  1. 從層次上,一個是關鍵字、一個是類, 這是最直觀的差別

  2. 從使用上,lock具有更大的靈活性,能夠控制鎖的釋放和獲取; 而synchronized的鎖的釋放是被動的,當出現異常或者同步代碼塊執行完之後,纔會釋放鎖

  3.  lock能夠判斷鎖的狀態、而synchronized沒法作到


lock能夠實現公平鎖、非公平鎖; 而synchronized只有非公平鎖

相關文章
相關標籤/搜索