【问题标题】:Thread safe remove/add element from one list to another线程安全地从一个列表中删除/添加元素到另一个列表
【发布时间】:2014-12-15 04:28:11
【问题描述】:

假设我有两个列表:fooListbarList。另外,假设我有两个线程:第一个遍历 fooList,如果满足某些条件(条件为真),它会从 fooList 中删除元素并将其添加到 barList。第二个遍历 barList,如果其他条件为真,则从 barList 中删除元素,并将其添加到 fooList。

我的处理方式是:

private static Object sharedLock = new Object();

Thread t1 = new Thread() {
    public void run() {
        synchronized (sharedLock) {

            for (Iterator<String> iterator = fooList.iterator(); iterator.hasNext();) {
                String fooElement = iterator.next();
                if (condition == true) {

                    iterator.remove();
                    barList.add(fooElement);

                }
            }

        }
    }
};

Thread t2 = new Thread() {
    public void run() {
        synchronized (sharedLock) {

            for (Iterator<String> iterator = barList.iterator(); iterator.hasNext();) {
                String barElement = iterator.next();
                if (otherCondition == true) {

                    iterator.remove();
                    fooList.add(barElement);

                }
            }

        }
    }
};

我想知道的是我处理得当吗?是否存在竞争条件的可能性?有没有更好的方法来实现相同的功能?

编辑看起来正确的实现方法是:

Thread t1 = new Thread() {
    public void run() {

        for (String fooElement : fooList) {
            if (condition == true) {

                fooList.remove(fooElement);
                barList.add(fooElement);

            }
        }

    }
};

Thread t2 = new Thread() {
    public void run() {

        for (String barElement : barList) {
            if (otherCondition == true) {

                barList.remove(barElement);
                fooList.add(barElement);

            }
        }

    }
};

其中:fooListbarList 的类型均为 CopyOnWriteArrayList&lt;String&gt;

【问题讨论】:

  • 如果您正在同步整个run 块,那么多线程毫无意义。
  • @ScaryWombat 所以,仅在条件下同步?
  • 不,使用 JDK 中 List 的线程安全实现

标签: java multithreading list iterator thread-safety


【解决方案1】:

不要重新发明轮子:使用来自 JDK 的 List 的线程安全实现:

List<String> fooList = new CopyOnWriteArrayList<>();

javadoc

【讨论】:

    【解决方案2】:

    您现在实现它的方式,t1t2 将按顺序运行,而不是并行运行。无论哪一个先开始,申请锁,执行他的整个循环,终止并为另一个释放锁。

    好消息是:没有竞争条件。不好的是:没有并行性。

    一般来说,如果可以避免的话,直接使用锁是个坏主意。 Java 包含大量专门用于并发使用的集合。见Java Concurrency Utils

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-24
      • 2022-11-13
      • 2021-05-08
      • 2016-02-26
      • 2015-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多