一个reentrant互斥锁和synchronized修饰的方法或代码作用大致相同,但它拥有着一些扩展性的功能。
使用案例:
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}}
代码:
public class ReentrantLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L;
/*提供实现AbstractQueuedSynchronizer 同步器的方法 */
Sync类作为ReentrantLock 的内部辅助类,继承于AbstractQueuedSynchronizer 用来实现AQS的一些同步方法并被它的子类NonfairSync 和FairSync 所使用
它直接为非公平锁类提供了nonfairTryAcquire方法,这个方法也是默认Acquire方法调用的对象
tryRelease:公平锁和非公平锁共用的释放锁方法
private final Sync sync;
/**子类在下面有公平和非公平版本的实现,使用AQS的状态标识(state)来代表持有锁的被占有情况
*/
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
abstract void lock();
/*执行非公平tryLock*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
/*首先调用AQS的getState方法来获取state状态,值默认初始为0*/
int c = getState();
/*为0,证明没有线程持有锁,利用原子操作将state+1,并将当前线程设为当前独享模式的持有者,然后返回true*/
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
/*若锁已被当前线程所占有,即状态值不为0,则将当前状态值设置为:当前状态值加上acquires参数(默认为1)。然后返回true。这块代码为可重入的体现*/
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
/*设置状态值为修改后的值*/
setState(nextc);
/*成功获锁*/
return true;
}
/*获取失败返回false*/
return false;
}
protected final boolean tryRelease(int releases) {
/*将当前状态值减去releases(默认1)*/
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
/*标志位,若c=0,则返回true,不为0.返回false*/
boolean free = false;
/*若修改后的状态值为0,则证明可以释放,并将持有当前独享模式的线程置空*/
if (c == 0) {
/*设置标志位为0*/
free = true;
setExclusiveOwnerThread(null);
}
/*设置修改后的状态值*/
setState(c);
return free;
}
/*判断是否持有独享模式*/
protected final boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
非公平锁的实现类,继承于Sync
/*非公平锁*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
final void lock() {
/*设置当前线程为独享模式的持有者,若当前state为0并且通过原子操作,则将其设为持有者,否则调用AQS的aquire方法*/
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
/*尝试获锁,默认非公平锁,调用nonfairTryAcquire方法*/
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
公平锁的实现类,继承于Sync
/*公平锁*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
/*获取state值*/
int c = getState();
/*公平的体现。若state为0*/
if (c == 0) {
/*当前节点为等待队列头节点并且能将state设置为acquires标识的值,则成功*/
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
/*若锁已被当前线程所占有,即状态值不为0,则将当前状态值设置为:当前状态值加上acquires参数(默认为1)。然后返回true。这块代码为可重入的体现*/
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
/*创建一个ReentrantLock的实例,这和使用ReentrantLock(flase)是一样的*/
public ReentrantLock() {
sync = new NonfairSync();
}
/*获锁*/
public void lock() {
sync.lock();
}
/*释放锁*/
public void unlock() {
sync.release(1);
}
使用:
package aa;
import java.util.concurrent.locks.ReentrantLock;
public class Aa {
static ReentrantLock lock = new ReentrantLock(true);
static class Bb implements Runnable {
int id;
public Bb(Integer id) {
this.id = id;
}
public void run() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i=0;i<3;i++){
lock.lock();
System.out.println("获得锁的线程:"+id);
lock.unlock();
}
}
}
public static void main(String[] args) {
for(int i=0;i<7;i++){
new Thread(new Bb(i)).start();
}
}
}
上面是公平锁的实现代码。运行后可以看到0到6几乎不重复出现,而非公平锁只需将true改为false,运行后可以发现0~6会成堆重复出现