【问题标题】:ArrayList ThreadSafety Test Code failsArrayList ThreadSafety 测试代码失败
【发布时间】:2011-10-06 21:40:54
【问题描述】:

鉴于,在 ArrayList 中添加方法定义如下:-

public boolean add(E e) {
ensureCapacity(size + 1);  // Increments modCount!!
elementData[size++] = e;
return true;
}

请查找以下程序来检查 ArrayList 的线程安全性。

package pack4;

import java.util.ArrayList;

public class Demo {

    public static void main(String[] args) {
        ArrayList<String> al = new ArrayList<String>() ;
        new AddFirstElementThread(al).start() ;
        new RemoveFirstElementThread(al).start() ;
    }
}

class AddFirstElementThread extends Thread{

    ArrayList<String> list ;

    public AddFirstElementThread(ArrayList<String> l) {
        list = l ;
    }

    @Override
    public void run() {
        while(true){
            if(list.size() == 0){
                list.add("First element") ;
            }
        }
    }
}

class RemoveFirstElementThread extends Thread{

    ArrayList<String> list ;

    public RemoveFirstElementThread(ArrayList<String> l) {
        list = l ;
    }

    @Override
    public void run() {
        while(true){
            if(list.isEmpty()){
                try{
                    list.get(0) ;
                    System.out.println("Hence Proved, that ArrayList is not Thread-safe.");
                    System.exit(1) ;
                }catch (Exception e) {
                        //continue, if no value is there at index 0
                }
            }
        }
    }
}

但是,程序永远不会终止,因此无法证明 ArrayList 的线程安全性。

请建议正确的实现来测试 ArrayList 和 Vector 的线程安全行为。

感谢和最好的问候,

Rits

【问题讨论】:

  • 嗯,事情是这样的。ArrayList 不是线程安全的,所以你将无法首先测试它。
  • 当然这种情况永远不会终止,你没有终止条件。如果你正在编写一个测试用例,你应该有一些终止条件。两个线程永远运行,就像你在每个线程中都有 while(true){ do stuff } 一样。
  • @Milhous : RemoveFirstElementThread 的运行方法中存在终止条件...
  • 只有在 RemoveFirstElement 线程第一次进入调用时列表为空时才会终止。否则它将永远运行。

标签: java multithreading collections thread-safety arraylist


【解决方案1】:

ArrayList 不是线程安全的; Vector 是。如果需要,您可以使用 Collections.synchronizedList() 包装 ArrayList

【讨论】:

  • 感谢您的快速回复。但我只是想为此编写一个测试用例。 :)
  • 为什么?你不认为作者知道如何使集合线程安全吗?我通常不测试核心课程。
  • 实际上,我是 Threads 的新手。只是探索基础知识。
  • @rits 您正在尝试测试未实现的行为。这样的测试会是什么样子?
【解决方案2】:

关于不安全代码的要点是不能保证在使用多线程时它的行为方式。你不能保证不安全的代码会失败。这是因为代码不是写成不安全的,它可能没有任何保证。线程安全只能通过阅读和理解代码来确定。

线程安全的问题是很难通过实验证明。除非您知道会触发问题的确切边缘情况,否则很难证明某些东西不是线程安全的。此外,线程安全问题的出现或多或少取决于系统的架构和负载。即它可以正常工作好几天并且无法预料地失败。

【讨论】:

  • 感谢这个很好的解释......,赞成:)
【解决方案3】:

在绝大多数情况下,集合上的“线程安全”是一个非常糟糕的主意,因为它太窄了,无论如何你需要一些更高级别的同步。

如果你真的想删除第一个元素或添加一个元素到列表中,你最好使用this here,但是你设计的例子可能需要更高的同步(取决于语义应该是什么) be - 如果你不明白为什么,阅读一些关于并发的东西可能是一个非常好的主意)

最后看看concurrent framework

【讨论】:

    猜你喜欢
    • 2010-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-12
    • 1970-01-01
    • 2021-09-11
    相关资源
    最近更新 更多