十三、併發程式設計之使用AQS重寫自己的鎖
阿新 • • 發佈:2018-12-14
package com.roocon.thread.ta2;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
public class MyLock2 implements Lock {
private Helper helper = new Helper() ;
private class Helper extends AbstractQueuedSynchronizer{
@Override
protected boolean tryAcquire(int arg) {
/**
* 如果第一個執行緒進來,可以拿到鎖,因此我們可以返回true
* 如果第二個執行緒進來,拿不到鎖,返回false,
* 有種特例,如果當前進來的執行緒和佔用排它鎖的執行緒是同一個執行緒(重入),則允許可以拿到鎖,但是要更新狀態值
* */
Thread t = Thread.currentThread();
//如何判斷是第一個執行緒進來還是其他執行緒進來
int state = getState();//拿到狀態
if(state==0) {//如果狀態等於0 ,無狀態(初始狀態)
if(compareAndSetState(0,arg)) {// 如果狀態等於0 ,將狀態設定為arg
setExclusiveOwnerThread(t);//設定佔用排它鎖的執行緒是當前執行緒
return true;
}
}else if(getExclusiveOwnerThread()==t){// 重入
setState(state+1);//更新狀態值
return true;
}
return false ;
}
@Override
protected boolean tryRelease(int arg) {
//鎖的獲取和釋放肯定是一一對應的,那麼呼叫此方法的執行緒一定是當前執行緒,如果不是丟擲異常
if(Thread.currentThread()!=getExclusiveOwnerThread()) {
throw new RuntimeException();
}
int state = getState()-arg;
boolean flag = false;
if(state==0) {//狀態為0,釋放鎖
setExclusiveOwnerThread(null);////設定佔用排它鎖的執行緒為空
flag = true;
}
setState(state);
return flag;
}
Condition newCondition() {
return new ConditionObject();
}
}
@Override
public void lock() {
helper.acquire(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
helper.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
return helper.tryAcquire(1);
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return helper.tryAcquireNanos(1, unit.toNanos(time));
}
@Override
public void unlock() {
helper.release(1);
}
@Override
public Condition newCondition() {
return helper.newCondition();
}
}
public class Main {
private int value;
private MyLock2 lock =new MyLock2();
public int next() {
lock.lock();//加鎖
try {
Thread.sleep(1000);
value++;
} catch (InterruptedException e) {
throw new RuntimeException();
} finally {
lock.unlock();//解鎖
}
return value;
}
public void a() {
lock.lock();
System.out.println("a");
b();
lock.unlock();
}
public void b() {
lock.lock();
System.out.println("b");
lock.unlock();
}
public static void main(String[] args) {
Main m = new Main();
//執行緒1
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
//測試執行緒安全問題
//System.out.println(Thread.currentThread().getName()+"----->"+m.next());
// 測試執行緒重入
m.a();
}
}
}) .start();
//執行緒2
// new Thread(new Runnable() {
// @Override
// public void run() {
// while(true) {
//測試執行緒安全問題
// System.out.println(Thread.currentThread().getName()+"----->"+m.next());
// }
// }
// }) .start();
// //執行緒3
// new Thread(new Runnable() {
// @Override
// public void run() {
// while(true) {
//測試執行緒安全問題
// System.out.println(Thread.currentThread().getName()+"----->"+m.next());
// }
// }
// }) .start();
}
}