Java 可重入锁实现原子性自增(ReentrantLock)

  • Post author:
  • Post category:java


可重入锁:可以对一个ReentrantLock对象多次执行lock()枷锁和unlock()释放锁。

公平锁:线程在加锁之前会查看AQS队列中有没有排队,如果有排队那么它会排到队列后面。

非公平锁:线程会直接加锁,不会查看AQS队列。

底层实现AbstractQueuedSynchronizer

ReentrantLock的两个构造方法(考虑公平策略和不考虑公平策略)

    // 不考虑公平策略
    public ReentrantLock() {
        sync = new NonfairSync();
    }
    // 考虑公平策略
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

公平锁对象和非公平锁对象

    // 公平锁定的同步对象
    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();
            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;
        }
    }
    
    // 非公平锁的同步对象
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

         // 执行锁定,立即尝试,失败时备份到正常状态
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

AQS核心结构

    // 用于指示节点正在共享模式下等待的标记
    // 共享模式指依据AQS的state控制状态,可以有多个满足条件的线程同时工作。
    static final Node SHARED = new Node();
    // 用于指示节点正在独占模式下等待的标记
    // 独占模式指AQS中的state控制状态,只有一个线程能够工作(其他线程进入阻塞状态)
    static final Node EXCLUSIVE = null;
    // 等待队列,专门存放那些加锁的线程
    // 等待队列的头,已延迟初始化。除了初始化,它只能通过方法sethead进行修改。注意:如果head存在,则保证其waitstatus不会被取消
    private transient volatile Node head;
    // 等待队列的尾部,已延迟初始化。仅通过方法enq修改以添加新的等待节点。
    private transient volatile Node tail;
    // 同步状态。可重入锁的核心,lock()+1,unlock()-1。
    private volatile int state;

原子性自增demo


github

public class AtomicityLock {

	private int count = 0;
	Lock lock = new ReentrantLock();
	private void increase() {
		lock.lock();
		try {
			count++;
		} finally {
			lock.unlock();
		}
	}

	public static void main(String[] args) {
		Long time = System.currentTimeMillis();
		final AtomicityLock atomicityLock = new AtomicityLock();
		for (int i = 0; i < 10; i++) {
			new Thread(new Runnable() {
				public void run() {
					for (int j = 0; j < 10000000; j++) {
						atomicityLock.increase();
					}
				}
			}).start();
		}
		while (Thread.activeCount() > 1) {
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("运行时间:" + (System.currentTimeMillis() - time));
		System.out.println("ReentrantLock(可重入锁):" + atomicityLock.count);
	}
	
}



版权声明:本文为qq_27243963原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。