java併發-Synchronized+CAS方式實現讀寫鎖
阿新 • • 發佈:2018-12-22
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();
}
}
}
}