1、啟動(dòng)文件
目前創(chuàng)新互聯(lián)公司已為上千的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)站空間、網(wǎng)站托管維護(hù)、企業(yè)網(wǎng)站設(shè)計(jì)、西盟網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶(hù)導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶(hù)和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
public class Main {
public static void main(String[] args) throws ParseException {
ReentrantLock lock = new ReentrantLock(true);
Thread t1 = new Thread(new Task(lock),"Thread-1");
Thread t2 = new Thread(new Task(lock),"Thread-2");
Thread t3 = new Thread(new Task(lock),"Thread-3");
t1.start();
t2.start();
t3.start();
}
}
2、Task
import java.util.concurrent.locks.ReentrantLock;
public class Task implements Runnable{
private ReentrantLock lock;
public Task(ReentrantLock lock) {
this.lock = lock;
}
@Override
public void run() {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + "獲取到鎖....");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + "釋放鎖....");
lock.unlock();
}
}
}
3、執(zhí)行結(jié)果:
protected final boolean tryAcquire(int acquires) { //參數(shù)是1
final Thread current = Thread.currentThread(); //當(dāng)前線(xiàn)程
int c = getState(); //獲取當(dāng)前同步狀態(tài)
if (c == 0) { //如果是0,則鎖沒(méi)有被占用
//等待隊(duì)列中,前面沒(méi)有其他等待的線(xiàn)程,則用CAS的方法更新同步狀態(tài)state
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current); //成功的話(huà),則設(shè)置鎖的占有線(xiàn)程為當(dāng)前線(xiàn)程
return true; //返回獲取資源成功
}
}
//如果鎖已經(jīng)被占用,則判斷是不是自己占用的
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;//如果是自己占用的,則是重入,增加state值,累加1
if (nextc < 0) //重入次數(shù)過(guò)大,拋出異常
throw new Error("Maximum lock count exceeded");
setState(nextc); //設(shè)置state值
return true; //重入返回ture
}
return false;//沒(méi)有獲取資源返回false
}
private Node addWaiter(Node mode) {
//把當(dāng)前線(xiàn)程包裝成節(jié)點(diǎn),準(zhǔn)備放入等待隊(duì)列
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
//嘗試直接把節(jié)點(diǎn)設(shè)置成隊(duì)尾,否則執(zhí)行enq
Node pred = tail;
if (pred != null) {
node.prev = pred;//當(dāng)前節(jié)點(diǎn)的上一個(gè)節(jié)點(diǎn)是之前的隊(duì)尾節(jié)點(diǎn)
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
//當(dāng)前節(jié)點(diǎn)插入隊(duì)尾
enq(node);
return node;
}
private Node enq(final Node node) {
//采用自旋,保證節(jié)點(diǎn)插入
for (;;) {
Node t = tail;
if (t == null) { // Must initialize 如果隊(duì)列為空,則創(chuàng)建一個(gè)空的節(jié)點(diǎn),設(shè)置為頭尾節(jié)點(diǎn)
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) { //隊(duì)列不為空,追加到隊(duì)尾
t.next = node;
return t;
}
}
}
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
//判斷節(jié)點(diǎn)的前任節(jié)點(diǎn)是不是頭節(jié)點(diǎn),頭節(jié)點(diǎn)是一個(gè)空節(jié)點(diǎn)
final Node p = node.predecessor();
//如果是頭節(jié)點(diǎn),則說(shuō)明當(dāng)前節(jié)點(diǎn)是隊(duì)列里的第一個(gè)節(jié)點(diǎn),首節(jié)點(diǎn)。
//則嘗試獲取鎖資源,此處因?yàn)門(mén)hread-1占用著資源,則失敗
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
//失敗之后,則判斷當(dāng)前節(jié)點(diǎn)線(xiàn)程Thread-2是不是可以阻塞
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;//前驅(qū)節(jié)點(diǎn)的狀態(tài)
if (ws == Node.SIGNAL) //如果是SIGNAL,則說(shuō)明前驅(qū)節(jié)點(diǎn)狀態(tài)可以喚醒后繼節(jié)點(diǎn),可以阻塞
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/
return true;
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
do {
node.prev = pred = pred.prev; //只有CANCELLED狀態(tài)大于0,則把取消狀態(tài)的節(jié)點(diǎn)從隊(duì)列刪除
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);//設(shè)置前驅(qū)節(jié)點(diǎn)為SIGNAL狀態(tài)
}
return false;
}
標(biāo)題名稱(chēng):多線(xiàn)程(十、AQS原理-ReentrantLock公平鎖)
文章來(lái)源:http://jinyejixie.com/article8/ppshop.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站維護(hù)、建站公司、小程序開(kāi)發(fā)、面包屑導(dǎo)航、網(wǎng)站內(nèi)鏈、域名注冊(cè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)