shouldParkAfterFailedAcquire

如果ThreadA的锁还没有释放的情况下,ThreadB和ThreadC来争抢锁肯定是会失败,那么失败以后会调用shouldParkAfterFailedAcquire方法

Node有5中状态,分别是:CANCELLED(1),SIGNAL(-1)、CONDITION(-2)、PROPAGATE(-3)、默认状态(0)

CANCELLED: 在同步队列中等待的线程等待超时或被中断,需要从同步队列中取消该Node的结点, 其结点的waitStatus为CANCELLED,即结束状态,进入该状态后的结点将不会再变化

SIGNAL: 只要前置节点释放锁,就会通知标识为SIGNAL状态的后续节点的线程

CONDITION: 和Condition有关系,后续会讲解

PROPAGATE:共享模式下,PROPAGATE状态的线程处于可运行状态

0:初始状态

这个方法的主要作用是,通过Node的状态来判断,ThreadA竞争锁失败以后是否应该被挂起。 

1. 如果ThreadA的pred节点状态为SIGNAL,那就表示可以放心挂起当前线程

2. 通过循环扫描链表把CANCELLED状态的节点移除

3. 修改pred节点的状态为SIGNAL,返回false. 

返回false时,也就是不需要挂起,返回true,则需要调用parkAndCheckInterrupt挂起当前线程

private static boolean 
shouldParkAfterFailedAcquire(Node pred, Node node) { 
	int ws = pred.waitStatus;//前置节点的
	waitStatus 
	if (ws == Node.SIGNAL)//如果前置节点为SIGNAL,意味着只需要等待其他前置节点的线程被释放, 
		return true;//返回true,意味着可以直接放心的挂起了 
		if (ws > 0) {//ws大于0,意味着prev节点取消了排队,直接移除这个节点就行 
		do { 
			node.prev = pred = pred.prev; 
			//相当于: pred=pred.prev; 
			node.prev=pred; 
		} while (pred.waitStatus > 0); //这里采用循环,从双向列表中移除CANCELLED的节点 
			pred.next = node; 
		} else {//利用cas设置prev节点的状态为SIGNAL(-1) 
		compareAndSetWaitStatus(pred, ws, 
		Node.SIGNAL); 
	} 
	return false; 
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值