当两个并发线程试图从CopyOnWriteArrayList中删除元素时会发生什么? java的

时间:2016-05-16 08:03:52

标签: java multithreading concurrency

在JAVA中发生了什么当两个并发线程试图从同一个CopyOnWriteArrayList中删除一些元素时?会有不确定的行为吗? 例如,如果列表中有1-10个整数, 1个线程删除前5个整数 2线程删除前3个整数 准确的结果是删除前5个整数的列表。 这会正常工作吗?

3 个答案:

答案 0 :(得分:1)

CopyOnWriteArrayList的行为取决于您使用的方法。

如果你在一个线程中使用5 remove(int index)而在另一个线程中使用3,那么你将删除8个元素,尽管哪个线程获得了未定义的元素。

如果你在一个线程中查找5个值remove(Integer element),而另一个线程中的前3个值是另一个线程,只要没有重复,前5个元素将被删除。前三个元素可以被任一个线程删除,留下没有删除元素的线程返回false

答案 1 :(得分:0)

CopyOnWriteArrayList实际上用于多线程环境,其中最佳结果,其中写入较少,读取次数较多

所有主题都带有List 的副本,原始列表左侧完好无损。在任何添加/删除操作之前,监视器会查看原始列表,每次写入列表时都会生成整个列表的副本,例如添加元素或删除元素synchronization发生的情况。

当您的列表太大时,这可能相当昂贵。 这意味着CopyOnWriteArrayList在我们进行少量修改但很多读取时非常有用,因为读取非常便宜并且不需要同步。

根据文件here

  

java.util.ArrayList的线程安全变体,其中所有变量都是   操作(添加,设置等)通过重新实现来实现   基础数组的副本。

答案 2 :(得分:0)

如果按索引删除,则将删除总共8(5 + 3)个元素。 因为,在一个线程删除一个元素后,新的CopyOnWriteArrayList将具有比之前执行删除的元素更少的元素。

package com.copyonwrite;

import java.util.concurrent.CopyOnWriteArrayList;

public class Main {
    public static void main(String[] args) {
        CopyOnWriteArrayList<String> cop = new CopyOnWriteArrayList<>();
        for (int i = 0; i < 10; i++)
            cop.add(Integer.toString(i));
        new Thread(new DeleteRunnable(cop, 5)).start();
        new Thread(new DeleteRunnable(cop, 3)).start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("size " + cop.size());
    }

    public static class DeleteRunnable implements Runnable {

        CopyOnWriteArrayList<String> cop;
        int cnt;

        public DeleteRunnable(CopyOnWriteArrayList<String> cop, int cnt) {
            this.cop = cop;
            this.cnt = cnt;
        }

        @Override
        public void run() {
            for (int i = 0; i < cnt; i++)
                cop.remove(i);
        }

    }
}

输出:大小2