美文网首页
juc8-Semaphore和CopyOnWriteArrayL

juc8-Semaphore和CopyOnWriteArrayL

作者: modou1618 | 来源:发表于2019-02-05 15:09 被阅读0次

一 Semaphore

  • 初始化并发数,允许最多多少个线程对共享资源访问。
  • 实例化,默认非公平模式
public Semaphore(int permits, boolean fair) {
    sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
  • class Sync extends AbstractQueuedSynchronizer控制并发,使用共享锁。
abstract static class Sync extends AbstractQueuedSynchronizer {
    private static final long serialVersionUID = 1192457210091910933L;

    Sync(int permits) {//初始化共享锁数量
        setState(permits);
    }

    final int getPermits() {
        return getState();
    }

    final int nonfairTryAcquireShared(int acquires) {
        for (;;) {//尝试获取锁,失败返回负数或成功返回正整数剩余锁数量
            int available = getState();
            int remaining = available - acquires;
            if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                return remaining;
        }
    }

    protected final boolean tryReleaseShared(int releases) {
        for (;;) {//释放共享锁
            int current = getState();
            int next = current + releases;
            if (next < current) // overflow
                throw new Error("Maximum permit count exceeded");
            if (compareAndSetState(current, next))
                return true;//cas修改直到修改成功
        }
    }

    final void reducePermits(int reductions) {
        for (;;) {//减少共享锁数量,直到成功
            int current = getState();
            int next = current - reductions;
            if (next > current) // underflow
                throw new Error("Permit count underflow");
            if (compareAndSetState(current, next))
                return;
        }
    }

    final int drainPermits() {
        for (;;) {//清空共享锁,获取剩余锁数量
            int current = getState();
            if (current == 0 || compareAndSetState(current, 0))
                return current;
        }
    }
}
  • 非公平锁,即tryAcquireShared()都会先尝试获取一次获取锁。
static final class NonfairSync extends Sync {
    private static final long serialVersionUID = -2694183684443567898L;

    NonfairSync(int permits) {
        super(permits);
    }

    protected int tryAcquireShared(int acquires) {
        return nonfairTryAcquireShared(acquires);
    }
}
  • 公平锁,先判断是否是等待锁链表第一个节点,是第一个才尝试获取共享锁,否则在队列中按先后顺序获取。
static final class FairSync extends Sync {
    private static final long serialVersionUID = 2014338818796000944L;

    FairSync(int permits) {
        super(permits);
    }

    protected int tryAcquireShared(int acquires) {
        for (;;) {
            if (hasQueuedPredecessors())
                return -1;
            int available = getState();
            int remaining = available - acquires;
            if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                return remaining;
        }
    }
}

二 CopyOnWriteArrayList

  • private transient volatile Object[] array;存储数据
  • get()函数直接按索引获取数组数据
  • 变更的操作都是加锁后,分配新的数组,拷贝原数组到新数组中。
  • add(),加锁控制添加元素
public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    lock.lock();//加锁
    try {
        Object[] elements = getArray();
        int len = elements.length;
        //新分配数组,拷贝元素到新数组中,赋值新增元素
        Object[] newElements = Arrays.copyOf(elements, len + 1);
        newElements[len] = e;
        setArray(newElements);//更新存储的数组为新数组
        return true;//返回true
    } finally {
        lock.unlock();
    }
}
  • set(),加锁设置指定索引数据
public E set(int index, E element) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] elements = getArray();
        E oldValue = get(elements, index);

        if (oldValue != element) {//更新数据
            int len = elements.length;
            //新分配数组,拷贝数据
            Object[] newElements = Arrays.copyOf(elements, len);
            newElements[index] = element;//修改数据
            setArray(newElements);//更新保存数据数组
        } else {
            // Not quite a no-op; ensures volatile write semantics
            setArray(elements);
        }
        return oldValue;
    } finally {
        lock.unlock();
    }
}

三 CopyOnWriteArraySet

  • 使用CopyOnWriteArrayList存储数组
  • 对存储数据做唯一性处理

相关文章

网友评论

      本文标题:juc8-Semaphore和CopyOnWriteArrayL

      本文链接:https://www.haomeiwen.com/subject/gcbysqtx.html