面试官:Java 有线程安全的 set 吗?我竟然答不上来。

Java研发军团

共 1686字,需浏览 4分钟

 ·

2021-11-15 09:14

来源:blog.csdn.net/li_canhui/article/details/91393247
= 0 ? false :        addIfAbsent(e, snapshot);}private static int indexOf(Object o, Object[] elements,                           int index, int fence) {    if (o == null) {        for (int i = index; i < fence; i++)            if (elements[i] == null)                return i;    } else {        for (int i = index; i < fence; i++)            if (o.equals(elements[i]))                return i;    }    return -1;}private boolean addIfAbsent(E e, Object[] snapshot) {    final ReentrantLock lock = this.lock;    lock.lock();    try {        Object[] current = getArray();        int len = current.length;        if (snapshot != current) {            // Optimize for lost race to another addXXX operation            int common = Math.min(snapshot.length, len);            for (int i = 0; i < common; i++)                if (current[i] != snapshot[i] && eq(e, current[i]))                    return false;            if (indexOf(e, current, common, len) >= 0)                    return false;        }        Object[] newElements = Arrays.copyOf(current, len + 1);        newElements[len] = e;        setArray(newElements);        return true;    } finally {        lock.unlock();    }}从源码可以看出,CopyOnWriteArraySet底层采用了CopyOnWriteArrayList数据结构来实现。在add元素时,采用的是可重入锁来实现线程安全。" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" wah-hotarea="click" style="outline: 0px; color: rgb(58, 58, 58); -webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;">在多线程环境下,要使用线程安全的集合,比如,ConcurrentHashMap是线程安全的HashMap,CopyOnWriteArrayList是线程安全的ArrayList。
= 0 ? false :        addIfAbsent(e, snapshot);}private static int indexOf(Object o, Object[] elements,                           int index, int fence) {    if (o == null) {        for (int i = index; i < fence; i++)            if (elements[i] == null)                return i;    } else {        for (int i = index; i < fence; i++)            if (o.equals(elements[i]))                return i;    }    return -1;}private boolean addIfAbsent(E e, Object[] snapshot) {    final ReentrantLock lock = this.lock;    lock.lock();    try {        Object[] current = getArray();        int len = current.length;        if (snapshot != current) {            // Optimize for lost race to another addXXX operation            int common = Math.min(snapshot.length, len);            for (int i = 0; i < common; i++)                if (current[i] != snapshot[i] && eq(e, current[i]))                    return false;            if (indexOf(e, current, common, len) >= 0)                    return false;        }        Object[] newElements = Arrays.copyOf(current, len + 1);        newElements[len] = e;        setArray(newElements);        return true;    } finally {        lock.unlock();    }}从源码可以看出,CopyOnWriteArraySet底层采用了CopyOnWriteArrayList数据结构来实现。在add元素时,采用的是可重入锁来实现线程安全。" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" wah-hotarea="click" style="outline: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;">那么HashSet对应的线程安全集合,是什么呢?java有没有提供默认实现呢?
= 0 ? false :        addIfAbsent(e, snapshot);}private static int indexOf(Object o, Object[] elements,                           int index, int fence) {    if (o == null) {        for (int i = index; i < fence; i++)            if (elements[i] == null)                return i;    } else {        for (int i = index; i < fence; i++)            if (o.equals(elements[i]))                return i;    }    return -1;}private boolean addIfAbsent(E e, Object[] snapshot) {    final ReentrantLock lock = this.lock;    lock.lock();    try {        Object[] current = getArray();        int len = current.length;        if (snapshot != current) {            // Optimize for lost race to another addXXX operation            int common = Math.min(snapshot.length, len);            for (int i = 0; i < common; i++)                if (current[i] != snapshot[i] && eq(e, current[i]))                    return false;            if (indexOf(e, current, common, len) >= 0)                    return false;        }        Object[] newElements = Arrays.copyOf(current, len + 1);        newElements[len] = e;        setArray(newElements);        return true;    } finally {        lock.unlock();    }}从源码可以看出,CopyOnWriteArraySet底层采用了CopyOnWriteArrayList数据结构来实现。在add元素时,采用的是可重入锁来实现线程安全。" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" wah-hotarea="click" style="outline: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;">在java的concurrent包中,我找到了CopyOnWriteArraySet,那么它是线程安全的吗?下面是测试代码。
= 0 ? false :        addIfAbsent(e, snapshot);}private static int indexOf(Object o, Object[] elements,                           int index, int fence) {    if (o == null) {        for (int i = index; i < fence; i++)            if (elements[i] == null)                return i;    } else {        for (int i = index; i < fence; i++)            if (o.equals(elements[i]))                return i;    }    return -1;}private boolean addIfAbsent(E e, Object[] snapshot) {    final ReentrantLock lock = this.lock;    lock.lock();    try {        Object[] current = getArray();        int len = current.length;        if (snapshot != current) {            // Optimize for lost race to another addXXX operation            int common = Math.min(snapshot.length, len);            for (int i = 0; i < common; i++)                if (current[i] != snapshot[i] && eq(e, current[i]))                    return false;            if (indexOf(e, current, common, len) >= 0)                    return false;        }        Object[] newElements = Arrays.copyOf(current, len + 1);        newElements[len] = e;        setArray(newElements);        return true;    } finally {        lock.unlock();    }}从源码可以看出,CopyOnWriteArraySet底层采用了CopyOnWriteArrayList数据结构来实现。在add元素时,采用的是可重入锁来实现线程安全。" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" wah-hotarea="click" style="outline: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;">public static void main(String[] args) {
    Set set = new CopyOnWriteArraySet<>();
    ExecutorService service = Executors.newFixedThreadPool(12);
    int times = 10000;
    AtomicInteger flag = new AtomicInteger(0);
    for(int i = 0; i < times; i ++){
        service.execute(()->{
            set.add("a" + flag.getAndAdd(1));
        });
    }
    service.shutdown();
    try {
        service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
    }catch (Exception e){
        e.printStackTrace();
    }
    System.out.println(set.size());
}
= 0 ? false :        addIfAbsent(e, snapshot);}private static int indexOf(Object o, Object[] elements,                           int index, int fence) {    if (o == null) {        for (int i = index; i < fence; i++)            if (elements[i] == null)                return i;    } else {        for (int i = index; i < fence; i++)            if (o.equals(elements[i]))                return i;    }    return -1;}private boolean addIfAbsent(E e, Object[] snapshot) {    final ReentrantLock lock = this.lock;    lock.lock();    try {        Object[] current = getArray();        int len = current.length;        if (snapshot != current) {            // Optimize for lost race to another addXXX operation            int common = Math.min(snapshot.length, len);            for (int i = 0; i < common; i++)                if (current[i] != snapshot[i] && eq(e, current[i]))                    return false;            if (indexOf(e, current, common, len) >= 0)                    return false;        }        Object[] newElements = Arrays.copyOf(current, len + 1);        newElements[len] = e;        setArray(newElements);        return true;    } finally {        lock.unlock();    }}从源码可以看出,CopyOnWriteArraySet底层采用了CopyOnWriteArrayList数据结构来实现。在add元素时,采用的是可重入锁来实现线程安全。" data-itemshowtype="0" tab="innerlink" data-linktype="2" wah-hotarea="click" hasload="1" style="outline: 0px; color: rgb(58, 58, 58); -webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;">经过多次执行,结果都是10000。可以说明,CopyOnWriteArraySet是线程安全的Set。
= 0 ? false :        addIfAbsent(e, snapshot);}private static int indexOf(Object o, Object[] elements,                           int index, int fence) {    if (o == null) {        for (int i = index; i < fence; i++)            if (elements[i] == null)                return i;    } else {        for (int i = index; i < fence; i++)            if (o.equals(elements[i]))                return i;    }    return -1;}private boolean addIfAbsent(E e, Object[] snapshot) {    final ReentrantLock lock = this.lock;    lock.lock();    try {        Object[] current = getArray();        int len = current.length;        if (snapshot != current) {            // Optimize for lost race to another addXXX operation            int common = Math.min(snapshot.length, len);            for (int i = 0; i < common; i++)                if (current[i] != snapshot[i] && eq(e, current[i]))                    return false;            if (indexOf(e, current, common, len) >= 0)                    return false;        }        Object[] newElements = Arrays.copyOf(current, len + 1);        newElements[len] = e;        setArray(newElements);        return true;    } finally {        lock.unlock();    }}从源码可以看出,CopyOnWriteArraySet底层采用了CopyOnWriteArrayList数据结构来实现。在add元素时,采用的是可重入锁来实现线程安全。" data-itemshowtype="0" tab="innerlink" data-linktype="2" wah-hotarea="click" hasload="1" style="outline: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;">那么CopyOnWriteArraySet是如何保证写入时的线程安全呢?以下是CopyOnWriteArraySet的add源码。
= 0 ? false :        addIfAbsent(e, snapshot);}private static int indexOf(Object o, Object[] elements,                           int index, int fence) {    if (o == null) {        for (int i = index; i < fence; i++)            if (elements[i] == null)                return i;    } else {        for (int i = index; i < fence; i++)            if (o.equals(elements[i]))                return i;    }    return -1;}private boolean addIfAbsent(E e, Object[] snapshot) {    final ReentrantLock lock = this.lock;    lock.lock();    try {        Object[] current = getArray();        int len = current.length;        if (snapshot != current) {            // Optimize for lost race to another addXXX operation            int common = Math.min(snapshot.length, len);            for (int i = 0; i < common; i++)                if (current[i] != snapshot[i] && eq(e, current[i]))                    return false;            if (indexOf(e, current, common, len) >= 0)                    return false;        }        Object[] newElements = Arrays.copyOf(current, len + 1);        newElements[len] = e;        setArray(newElements);        return true;    } finally {        lock.unlock();    }}从源码可以看出,CopyOnWriteArraySet底层采用了CopyOnWriteArrayList数据结构来实现。在add元素时,采用的是可重入锁来实现线程安全。" data-itemshowtype="0" tab="innerlink" data-linktype="2" wah-hotarea="click" hasload="1" style="outline: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;">public boolean add(E e) {
    return al.addIfAbsent(e);
}
public boolean addIfAbsent(E e) {
    Object[] snapshot = getArray();
    return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
        addIfAbsent(e, snapshot);
}
private static int indexOf(Object o, Object[] elements,
                           int index, int fence) {
    if (o == null) {
        for (int i = index; i < fence; i++)
            if (elements[i] == null)
                return i;
    } else {
        for (int i = index; i < fence; i++)
            if (o.equals(elements[i]))
                return i;
    }
    return -1;
}
private boolean addIfAbsent(E e, Object[] snapshot) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] current = getArray();
        int len = current.length;
        if (snapshot != current) {
            // Optimize for lost race to another addXXX operation
            int common = Math.min(snapshot.length, len);
            for (int i = 0; i < common; i++)
                if (current[i] != snapshot[i] && eq(e, current[i]))
                    return false;
            if (indexOf(e, current, common, len) >= 0)
                    return false;
        }
        Object[] newElements = Arrays.copyOf(current, len + 1);
        newElements[len] = e;
        setArray(newElements);
        return true;
    } finally {
        lock.unlock();
    }
}

= 0 ? false :        addIfAbsent(e, snapshot);}private static int indexOf(Object o, Object[] elements,                           int index, int fence) {    if (o == null) {        for (int i = index; i < fence; i++)            if (elements[i] == null)                return i;    } else {        for (int i = index; i < fence; i++)            if (o.equals(elements[i]))                return i;    }    return -1;}private boolean addIfAbsent(E e, Object[] snapshot) {    final ReentrantLock lock = this.lock;    lock.lock();    try {        Object[] current = getArray();        int len = current.length;        if (snapshot != current) {            // Optimize for lost race to another addXXX operation            int common = Math.min(snapshot.length, len);            for (int i = 0; i < common; i++)                if (current[i] != snapshot[i] && eq(e, current[i]))                    return false;            if (indexOf(e, current, common, len) >= 0)                    return false;        }        Object[] newElements = Arrays.copyOf(current, len + 1);        newElements[len] = e;        setArray(newElements);        return true;    } finally {        lock.unlock();    }}从源码可以看出,CopyOnWriteArraySet底层采用了CopyOnWriteArrayList数据结构来实现。在add元素时,采用的是可重入锁来实现线程安全。" data-itemshowtype="0" tab="innerlink" data-linktype="2" wah-hotarea="click" hasload="1" style="outline: 0px; color: rgb(58, 58, 58); -webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;">从源码可以看出,CopyOnWriteArraySet底层采用了CopyOnWriteArrayList数据结构来实现。在add元素时,采用的是可重入锁来实现线程安全。


END


推荐阅读

一键生成Springboot & Vue项目!【毕设神器】

Java可视化编程工具系列(一)

Java可视化编程工具系列(二)


顺便给大家推荐一个GitHub项目,这个 GitHub 整理了上千本常用技术PDF,绝大部分核心的技术书籍都可以在这里找到,

GitHub地址:https://github.com/javadevbooks/books

Gitee地址:https://gitee.com/javadevbooks/books

电子书已经更新好了,你们需要的可以自行下载了,记得点一个star,持续更新中..



浏览 20
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报