java并发之AQS

  • AQS 是什么
    简单来说,就是来说就是一个数+一个FIFO的双端队列
    如图所示:
    java并发之AQS_第1张图片
    当state成为我们想要的值,线程可以进行运行,否则进行排队在CLH末尾加入,state使用cas算法进行操作,可以解决并发时的安全问题。

  • CAS 是一种比较交换算法,现代的计算机的CPU有这条指令,jdk5.0后,jdk提供了使用的方式,大概的逻辑就是如果另一个线程看到的值还是expect,代表没有被其他线程修改,然后进行update操作。

	 /**
     * Atomically sets synchronization state to the given updated
     * value if the current state value equals the expected value.
     * This operation has memory semantics of a {@code volatile} read
     * and write.
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that the actual
     *         value was not equal to the expected value.
     */
    protected final boolean compareAndSetState(int expect, int update) {
        // See below for intrinsics setup to support this
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }
  • synchronized
    是java中加锁的关键字,在jdk1.6之后的版本对其进行了优化,首先一个线程获得了锁,锁就进入了偏向,如果锁偏向失败,锁会升级为轻量级锁(大多数是自旋锁,执行几次空的循环,等待可以获取锁),再失败就是悲观锁synchronized。
    同时synchronized的锁是需要jvm调用操作系统底层进行实现,再用户态和kernel中进行切换,消耗时间。
  1. AQS 使用场景
    具体的使用需要继承AbstractQueuedSynchronizer重写其中的tryAcquire和tryRelease方法,实例如下:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;

public class LockDemo {
    private static Sync sync = new Sync();
    private static volatile int m = 0;

    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(() -> {
                try {
                    sync.acquire(1);
                    for (int j = 0; j < 100; j++) {
                        m++;
                    }
                } finally {
                    sync.release(1);
                }
            });
        }
        for (Thread thread : threads) {
            thread.start();
        }
        for (Thread thread : threads) {
            thread.join();
        }
        System.out.println(m);
    }

    private static class Sync extends AbstractQueuedSynchronizer {
        @Override
        protected boolean tryAcquire(int arg) {
            //0: 没有占有 1: 占用
            if (compareAndSetState(0, 1)) {
                //互斥锁
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        @Override
        protected boolean tryRelease(int arg) {
            if (!isHeldExclusively()) {
                throw new IllegalMonitorStateException();
            }
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        @Override
        protected boolean isHeldExclusively() {
            //是否被当前线程独占
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        Condition newCondition() {
            return new ConditionObject();
        }

        // Deserializes properly
        private void readObject(ObjectInputStream s)
                throws IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }
}

  1. AQS 实际应用
    ReetrantLock
    CountDownLatch
    Semaphore
    ReetrantReadWriteLock
    这些都是底层都是使用的AQS

你可能感兴趣的:(java,基础)