1. 程式人生 > >java併發-Synchronized+CAS方式實現讀寫鎖

java併發-Synchronized+CAS方式實現讀寫鎖

Synchronized+CAS方式實現讀寫鎖

文章目錄

思路

  • 讀可讀
  • 讀不能寫
  • 寫不能讀
  • 寫不可寫

技術

  • CAS 無鎖機制,執行緒安全的更新讀寫狀態
  • synchronized 讀執行緒的資源控制,控制寫寫的情況

程式碼

/**
 * describe:
 * E-mail:[email protected]  date:2018/12/16
 * 讀:readLock readUnLock 兩個方法區輔助,更新writeState
 * 寫 writeLock 同步target資源,防止多個寫操作target,寫操作更新readState的狀態
 * @Since 0.0.1
 */
public class SynchronizerRW<T> {

    //讀的狀態,0可讀,非0不可讀
    private volatile int readState = 0;
    //寫的狀態,0可寫,非0不可寫
    private
volatile int writeState = 0; //操作共享目標,執行緒不安全的起源 private T target; //java CAS操作類 private static final Unsafe unsafe; //讀寫state的偏移量 private static final long readStateOffSet; private static final long writeStateOffSet; /** * Unsafe的例項化,不能通過getUnsafe()方法來獲取,因為,classLoader不一樣,不被Unsafe信任。 * 必須通過正規化來拿到Unsafe物件 */
static { try { //反射操作 Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); unsafe = (Unsafe) field.get(null); //設定偏移量 readStateOffSet = unsafe.objectFieldOffset (SynchronizerRW.class.getDeclaredField("readState")); writeStateOffSet = unsafe.objectFieldOffset (SynchronizerRW.class.getDeclaredField("writeState")); } catch (Exception e) { throw new Error(e); } } /** * 初始化共享變數 * @param target */ public SynchronizerRW(T target) { if (null == target) throw new IllegalArgumentException("target must not be null !"); this.target = target; } /** * CAS 設定讀取state的狀態 * @param expect * @param update * @return */ private boolean compareAndSetReadState(int expect, int update) { return unsafe.compareAndSwapInt(this, readStateOffSet, expect, update); } /** * CAS設定寫state的狀態 * @param expect * @param update * @return */ private boolean compareAndSetWriteState(int expect, int update) { return unsafe.compareAndSwapInt(this, writeStateOffSet, expect, update); } /** * 讀執行緒獲取讀的許可權 * 自旋+CAS * readState=0 的前提下,多執行緒同事寫的話,會出現執行緒不安全(原子性、可見性、有序性),通過CAS+volatile可以解決 * @return */ public T readLock() { for (; ; ) { //可讀 if (readState == 0 && compareAndSetWriteState(writeState, writeState + 1)) { //這裡可以返回 return target; } } } /** * 與readLock成對出現 */ public void readUnLock() { for (; ; ) { if (compareAndSetWriteState(writeState, writeState - 1)) { return; } } } /** * writeState=0前提下,去CAS修改readState,修改成功後就去獲取target的monitor * @param write */ public void writeLock(Write<T> write) { for (; ; ) { if (writeState == 0 && compareAndSetReadState(readState, readState + 1)) { //可以去爭奪鎖 break; } } //防止多個讀執行緒操作共享變數 synchronized (target) { //寫操作 write.modify(target); readState--; } } /** * 寫操作的回撥 * @param <T> */ public interface Write<T> { void modify(T t); } }

測試

/**
 * describe:
 * E-mail:[email protected]  date:2018/12/16
 *
 * @Since 0.0.1
 */
public class SynchronizedWRTest {

    static class Student {
        int count = 0;

        public int getCount() {
            return count;
        }

        public void setCount(int count) {
            this.count = count;
        }

        @Override
        public String toString() {
            return count + "==" + Thread.currentThread().getName();
        }
    }

    static class ReadThread extends Thread {
        private SynchronizerRW<Student> studentSynchronizerRW;

        public ReadThread(SynchronizerRW<Student> studentSynchronizerRW) {
            this.studentSynchronizerRW = studentSynchronizerRW;
        }

        @Override
        public void run() {
            System.out.println("讀執行緒程:" + studentSynchronizerRW.readLock());
            studentSynchronizerRW.readUnLock();
        }
    }

    static class WriteThread extends Thread {
        private SynchronizerRW<Student> studentSynchronizerRW;

        public WriteThread(SynchronizerRW<Student> studentSynchronizerRW) {
            this.studentSynchronizerRW = studentSynchronizerRW;
        }

        @Override
        public void run() {
            studentSynchronizerRW.writeLock(student -> {
                System.out.println("寫執行緒寫開始:" + student);
                student.count++;
                System.out.println("寫執行緒寫結束:" + student);
            });
        }
    }

    public static void main(String[] args) {
        SynchronizerRW<Student> studentSynchronizerRW = new SynchronizerRW<>(new Student());
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0) {
                Thread t = new ReadThread(studentSynchronizerRW);
                t.start();
            } else {
                Thread t = new WriteThread(studentSynchronizerRW);
                t.start();
            }
        }
    }
}

結果

在這裡插入圖片描述

GitHub主頁