欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识

所有的互斥访问都在 劳务派遣管理系统 这个lock的try finally中实现

点击: 次  来源:宝鼎软件 时间:2017-05-31

原文出处: 阿凡卢

本文扼要先容Java并发编程方面常用的类和荟萃,并先容下其实现道理。

AtomicInteger

可以用原子方法更新int值。类 AtomicBoolean、AtomicInteger、AtomicLong 和 AtomicReference 的实例各自提供对相应范例单个变量的会见和更新。根基的道理都是利用CAS操纵:

boolean compareAndSet(expectedValue, updateValue);

假如此要领(在差异的类间参数范例也差异)当前保持expectedValue,则以原子方法将变量配置为updateValue,并在乐成时陈诉true。

轮回CAS,参考AtomicInteger中的实现:

public final int getAndIncrement() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return current;
        }
    }

    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

ABA问题

因为CAS需要在操纵值的时候查抄下值有没有产生变革,假如没有产生变革则更新,可是假如一个值本来是A,酿成了B,又酿成了A,那么利用CAS举办查抄时会发明它的值没有产生变革,可是实际上却变革了。ABA问题的办理思路就是利用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加一,那么A-B-A 就会酿成1A-2B-3A。

从Java1.5开始JDK的atomic包里提供了一个类AtomicStampedReference来办理ABA问题。这个类的compareAndSet要领浸染是首先查抄当前引用是否便是预期引用,而且当前符号是否便是预期符号,假如全部相等,则以原子方法将该引用和该符号的值配置为给定的更新值。

public boolean compareAndSet(
        V      expectedReference,//预期引用
        V      newReference,//更新后的引用
        int    expectedStamp, //预期符号
        int    newStamp) //更新后的符号

ArrayBlockingQueue

一个由数组支持的有界阻塞行列。此行列按 FIFO(先进先出)原则对元素举办排序。行列的头部是在行列中存在时间最长的元素。行列的尾部是在行列中存在时间最短的元素。新元素插入到行列的尾部,行列获取操纵则是从行列头部开始得到元素。这是一个典范的“有界缓存区”,牢靠巨细的数组在个中保持出产者插入的元素和利用者提取的元素。一旦建设了这样的缓存区,就不能再增加其容量。试图向已满行列中放入元素会导致操纵受阻塞;试图从空行列中提取元素将导致雷同阻塞。

此类支持对期待的出产者线程和利用者线程举办排序的可选公正计策。默认环境下,不担保是这种排序。然而,通过将公正性(fairness)配置为true而结构的行列答允凭据 FIFO 顺序会见线程。公正性凡是会低落吞吐量,劳务派遣管理系统,但也淘汰了可变性和制止了“不服衡性”。

一些源代码参考:

/** Main lock guarding all access */
    final ReentrantLock lock;

    public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
                notFull.await();
            insert(e);
        } finally {
            lock.unlock();
        }
    }

    private void insert(E x) {
        items[putIndex] = x;
        putIndex = inc(putIndex);
        ++count;
        notEmpty.signal();
    }

    final int inc(int i) {
        return (++i == items.length) ? 0 : i;
    }

    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return extract();
        } finally {
            lock.unlock();
        }
    }

    private E extract() {
        final Object[] items = this.items;
        E x = this.<E>cast(items[takeIndex]);
        items[takeIndex] = null;
        takeIndex = inc(takeIndex);
        --count;
        notFull.signal();
        return x;
    }

    final int dec(int i) {
        return ((i == 0) ? items.length : i) - 1;
    }

    @SuppressWarnings("unchecked")
    static <E> E cast(Object item) {
        return (E) item;
    }

ArrayBlockingQueue只利用了一个lock来节制互斥会见,所有的互斥会见都在这个lock的try finally中实现。

LinkedBlockingQueue

一个基于已链接节点的、范畴任意的blocking queue。此行列按 FIFO(先进先出)排序元素。行列的头部是在行列中时间最长的元素。行列的尾部是在行列中时间最短的元素。新元素插入到行列的尾部,而且行列获取操纵会得到位于行列头部的元素。链接行列的吞吐量凡是要高于基于数组的行列,可是在大大都并发应用措施中,其可预知的机能要低。