java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java 并发锁ReentrantLock

Java 并发锁ReentrantLock的实现

作者:暮年

本文主要介绍了Java 并发锁ReentrantLock的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

全路径名:java.util.concurrent.locks.ReentrantLock 类定义如下:

/**
 * @since 1.5
 */
public class ReentrantLock implements Lock, java.io.Serializable {
    ...
}

ReentrantLock 类实现了 Lock 接口,JDK1.5 引入。

ReentrantLock 使用上分公平锁和非公平锁,两种锁机制。默认无参构造方法 ReentrantLock() 创建的是非公平锁。可以使用有参构造函数 ReentrantLock(boolean fair) 选择使用公平锁,还是非公平锁。具体实现是通过 ReentrantLock 的内部类 FairSync 和 NonfairSync 来实现的。FairSync 和 NonfairSync 是 ReentrantLock 类中抽象内部类 Sync 的子类。具体源码如下:

public class ReentrantLock implements Lock, java.io.Serializable {
    ...
    private final Sync sync;
    ...
    abstract static class Sync extends AbstractQueuedSynchronizer {...}
    static final class NonfairSync extends Sync {...}
    static final class FairSync extends Sync {...}
    public ReentrantLock() {
        sync = new NonfairSync();
    }
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
    public void lock() {
        sync.lock();
    }
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }
    public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }
    public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }
    public void unlock() {
        sync.release(1);
    }
    public Condition newCondition() {
        return sync.newCondition();
    }
    ...
}

java.util.concurrent.locks.Lock 接口定义了5个方法。具体源码如下:

public interface Lock {
    void lock();
    void lockInterruptibly() throws InterruptedException;
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    void unlock();
    Condition newCondition();
}

通过对 ReentrantLock 类 Lock 接口 lock() 方法的实现, 来看 ReentrantLock 是如何实现公平锁的。

先说方式,再看源码更好理解一点。如果要公平,那就要有先来后到。就像超市购物结账一样:

ReentrantLock 内部类 FairSync 负责实现公平锁机制,FairSync 类继承了 Sync 类,Sync类 继承了 AbstractQueuedSynchronizer 类。下面是与 lock() 方法有个的源码:

static final class FairSync extends Sync {

    final void lock() {
            acquire(1);
    }

    protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                    if (!hasQueuedPredecessors() &&
                            compareAndSetState(0, acquires)) {
                            setExclusiveOwnerThread(current);
                            return 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;
    }
}
public abstract class AbstractQueuedSynchronizer
    extends AbstractOwnableSynchronizer
    implements java.io.Serializable {
    ...
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
    ...
    private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail;
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }
    ...
    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) 
                        && parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
}

FairSync 的 lock() 方法调用 AbstractQueuedSynchronizer 类 acquire() 方法获取锁。AbstractQueuedSynchronizer 类 acquire() 方法中,先使用 FairSync 类的 tryAcquire() 方法实现没有人排队的场景。

AbstractQueuedSynchronizer 类 acquire() 方法中,如果没人排队的情况下,未能成功抢到锁。那就进入了排队的场景:

看完 ReentrantLock 公平锁的实现,非公平锁的实现就简单了。非公平锁是通过 ReentrantLock 内部类 实现的,源码如下:

static final class NonfairSync extends Sync {
    final void lock() {
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
            acquire(1);
    }
    protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
    }
}
abstract static class Sync extends AbstractQueuedSynchronizer {
    ...
    final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
    }
    ...
}

从源码看一看出,不排队,直接调用 compareAndSetState(0, 1) 方法抢。这就是非公平锁。

到此这篇关于Java 并发锁ReentrantLock的实现的文章就介绍到这了,更多相关Java 并发锁ReentrantLock内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文