首页 > 试题广场 >

下列关于Java并发的说法中正确的是()

[单选题]
下列关于Java并发的说法中正确的是()
  • CopyOnWriteArrayList适用于写多读少的并发场景
  • ReadWriteLock适用于读多写少的并发场景
  • ConcurrentHashMap的写操作不需要加锁,读操作需要加锁
  • 只要在定义int类型的成员变量i的时候加上volatile关键字,那么多线程并发执行i++这样的操作的时候就是线程安全的了
推荐
答案:B

A,CopyOnWriteArrayList适用于写少读多的并发场景
B,ReadWriteLock即为读写锁,他要求写与写之间互斥,读与写之间互斥,
   读与读之间可以并发执行。在读多写少的情况下可以提高效率
C,ConcurrentHashMap是同步的HashMap,读写都加锁
D,volatile只保证多线程操作的可见性,不保证原子性
编辑于 2015-06-17 21:16:02 回复(19)
B
对于D选项,volatite只保证线程在“加载数据阶段”加载的数据是最新的,并不能保证线程安全。

一个线程执行的过程有三个阶段:
加载(复制)主存数据到操作栈 -->  对操作栈数据进行修改  --> 将操作栈数据写回主存
volatite关键字,让编译器不去优化代码使用缓存等,以保证线程在“加载数据阶段”加载的数据都是最新的

比如:
某一时刻i=6是最新的值,volatile保证线程A,B都同时加载了这个最新的值,
然后A执行i(A)+1=7,然后将7写回主存,
B也执行i(B)+1=7,然后也将7写回内存,
这样,执行两次加法,i却只增加了1
发表于 2015-08-20 10:55:22 回复(7)

CopyOnWriteArrayList的实现原理

在使用CopyOnWriteArrayList之前,我们先阅读其源码了解下它是如何实现的。以下代码是向ArrayList里添加元素,可以发现在添加的时候是需要加锁的,否则多线程写的时候会Copy出N个副本出来。

public boolean add(T 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;

    } finally {

        lock.unlock();

    }

}

final void setArray(Object[] a) {
    array = a;
}

读的时候不需要加锁,如果读的时候有多个线程正在向ArrayList添加数据,读还是会读到旧的数据,因为写的时候不会锁住旧的ArrayList。

public E get(int index) {
    return get(getArray(), index);
} CopyOnWriteArrayList适用于读多写少的并发场景

发表于 2016-03-29 18:48:44 回复(8)
A:CopyOnWrite适用于读多写少的并发场景。
B:正确
C:ConcurrentHashMap,读操作不需要加锁,写操作需要加锁
D:对于volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的
发表于 2015-06-11 15:13:11 回复(0)
Copy-On-Write简称COW,是一种用于程序设计中的优化策略。其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略。
发表于 2015-08-12 21:34:00 回复(1)
A:CopyOnWrite并发容器用于读多写少的并发场景,Copy-On-Write简称COW,是一种用于程序设计中的优化策略。其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略。从JDK1.5开始Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们是CopyOnWriteArrayListCopyOnWriteArraySet
C:在JDK1.7之前,ConcurrentHashMap是通过分段锁机制来实现的,所以其最大并发度受Segment的个数限制。因此,在JDK1.8中,ConcurrentHashMap的实现原理摒弃了这种设计,而是选择了与HashMap类似的数组+链表+红黑树的方式实现,而加锁则采用CASsynchronized实现。读写都加锁
D:volatile保证内存可见性有序性(内存屏障实现),不能保证原子性
编辑于 2019-05-30 20:30:41 回复(1)
对于volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的,同时线程工作内存中的操作并不是原子性的。所以在一个线程对该变量进行操作的同时,其他的线程有可能也在对该变量进行操作。
发表于 2015-08-16 19:57:23 回复(0)
ReadWriteLock写与写之间互斥,读与写之间互斥,读与读之间并发,所以适用于读多写少
发表于 2015-08-09 09:41:26 回复(0)
ReadWriteLock 读 -- 读 不互斥  写--写 互斥 ; B错在哪里我想知道有解释一下的吗?
发表于 2015-02-11 16:31:02 回复(1)
b
ReadWriteLock解决了这个问题,当写操作时,其他线程无法读取或写入数据,而当读操作时,其它线程无法写入数据,但却可以读取数据 。
发表于 2015-05-31 12:57:10 回复(0)
CopyOnWrite指的是修改容器之前,先将原来的容器拷贝一份副本,在副本中进行修改,修改之后使用原来的容器指向修改好的容器,这样保证了两个容器可以同时读,用于读多于写的场景
发表于 2017-11-12 10:06:21 回复(0)
发表于 2022-03-04 20:51:28 回复(0)
关于选项D,我想补充一点,那就是之所以volatile不能保证i++的线程安全,除了volatile只能保证可见性之外,与 i++ 不是原子操作也有关,如果换个场合,有些人可能就会把 i++ 误当成原子操作,其实不是的,因为i++做了三次指令操作:
1.从内存中读取i 变量的值到CPU的寄存器;
2.在寄存器中的i自增1;
3.将寄存器中的值写入内存;

发表于 2020-02-22 11:05:27 回复(0)
答案:B A,CopyOnWriteArrayList适用于写少读多的并发场景 B,ReadWriteLock即为读写锁,他要求写与写之间互斥,读与写之间互斥,    读与读之间可以并发执行。在读多写少的情况下可以提高效率 C,ConcurrentHashMap是同步的HashMap,读写都加锁 D,volatile只保证多线程操作的可见性,不保证原子性
发表于 2017-11-22 09:07:17 回复(0)
volatile变量有两个作用:
1. 保证可见性,写的时候会通知主内存更新,读的时候会强制从主内存读到工作内存中。
2. 防止指令重排序。

CopyOnWriteArrayList只在写操作加锁,在读操作不加锁
ReadWriteLock,读写锁,写写互斥,读写互斥、读读不互斥

ConcurrentHashMap读写都加了锁

发表于 2016-09-01 15:03:02 回复(3)
CopyOnWriteArrayList适用于读多写少的并发场景
ReadWriteLock即为读写锁,他要求写与写之间互斥,读与写之间互斥,读与读之间可以并发执行。在读多写少的情况下可以提高效率。
ConcurrentHashMap是同步的HashMap,读写都加锁
发表于 2021-04-29 16:52:45 回复(0)
1、CopyOnWriteArrayList适用于写少读多的场景
2、ReadWriteLock读写锁,写写互斥、读写互斥、读读并发,在读多写少的情况下提高效率
3、ConcurrentHashMap读写都加锁
4、volatile 保证可见性
发表于 2017-10-19 14:11:42 回复(0)
CopyOnWriteArrayList用于替代同步List,提供更好的并发性能。写入时复制(Copy-On-Write)是每当修改时就会复制,这需要一定的开销。仅当迭代操作远远多于修改操作时,才应该使用写入时复制。即适用于读多写少。
发表于 2017-06-30 20:17:23 回复(0)
有啥类适合写多读少的
发表于 2017-02-17 10:42:37 回复(2)
B
发表于 2015-05-19 22:46:16 回复(0)
b
发表于 2015-04-04 20:29:14 回复(0)