java - 为什么这个方法会导致并发问题呢?

标签 java multithreading

我同步了下面的代码,但它会导致并发问题。

我知道这是由多线程引起的,我对 synchronized 关键字感到困惑。我预计 list.length 值为 100。我该如何修复它?

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class ThreadA extends Thread {

    private static byte[] lock = new byte[0];

    private static final List<String> list = new ArrayList<String>();

    @Override
    public void run() {

        System.out.println(list.size());

        synchronized(lock) {
            int size = list.size();
            if( size == 0 ) return;

            if(size >= 100) {
                list.clear();
            }
        }

    }

    public void add(String s) {
        list.add(s);
    }

    public static void main(String[] args) {

        for(int i = 0; i < 100; i++) {
            new ThreadA().start();
            new Thread(new Runnable() {

                @Override
                public void run() {
                    synchronized(lock) {
                        for(int m = 0; m < 100; m++) {
                            list.add(new Date().toLocaleString());
                        }
                    }
                }
            }).start();
        }

        System.out.println("LIST.SIZE:" + list.size());
    }

}

最佳答案

两个问题:

  1. println 访问 list 时无需同步,也无需等待线程完成。您将获得当时列表的值。

  2. 无法保证线程的执行顺序。可能会发生所有 ThreadA 实例在匿名线程之前运行的情况,并且结果可能是一个明显大于 100 的值。

关于java - 为什么这个方法会导致并发问题呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17000739/

相关文章:

java - Glassfish 中的容器管理安全性

java - 如何覆盖 .properties 中的一个属性而不覆盖整个文件?

java - Libgdx Sprite 不在浏览器中绘制

java - 无法在 Android Activity 布局 XML 文件中实例化自定义类

c# - 如何为 PLINQ 重新实现 Where() 运算符?

java - 如何在使用执行器的同时启动线程?

java - 如何使用aspectj跟踪Java父线程id?

java - == 与 Enum name() 和 toString()

ruby - 作为开发人员,不同的 Ruby 线程模型(Ruby 与 JRuby)对您的代码有什么实际影响?

c++ - 多个线程可以安全地同时向同一个变量写入相同的值吗?