简体   繁体   English

两个线程之间的同步Arraylist不会返回相同的值

[英]Synchronized Arraylist between two threads doesn't return the same value

I have following code : 我有以下代码:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class MyThread implements Runnable{

    private List<Integer> myList;

    public MyThread(List<Integer> list){
            this.myList = list;
    }
    private void updateList(int i){
           synchronized (myList) {
               myList.add(i);
           }
    }
    @Override
    public void run() {
        for( int i = 0; i < 1000000;i++){
                updateList(i);
        }
        System.out.println("end: " + myList.size());
    }
}
public class MyExecutor {

    private List<Integer> taskList = new ArrayList<>();
    private void launch(){

        ExecutorService executorService= Executors.newFixedThreadPool(10000);
        executorService.execute(new MyThread(taskList));
        executorService.execute(new MyThread(taskList));
        executorService.shutdown();
    }
    public static void main(String[] args) {
        MyExecutor test = new MyExecutor();
        test.launch();
    }
}

the output should be : 2000000 输出应为: 2000000

I will get different result which means these two threads are replacing each other's value. 我将得到不同的结果,这意味着这两个线程正在替换彼此的值。

I can't figure out where is the problem, tried several modifications on this code but none of them has fixed the problem. 我不知道问题出在哪里,对此代码进行了几次修改,但都没有解决问题。 (replaced with Vector / added synchronize in constructor / added volatile) (用Vector替换/在构造函数中添加了同步/在volatile中添加了)

Why doesn't this code work correctly? 为什么此代码无法正常工作?

Edit 编辑

At both thread I expect to get 1000000 在两个线程我预计将获得1000000

the output should be : 2000000 输出应为:2000000

No, for three reasons: 否,原因如下:

  1. You are printing two things, so the output won't be a single number. 您要打印两件事,因此输出不会是一个数字。
  2. It prints the size when each thread happens to have added 1000000 things; 当每个线程恰好添加了1000000个东西时,它将打印大小; you know nothing about how much the other thread has done at this point. 您不知道其他线程在这一点上做了多少。
  3. You are not accessing the size in a synchronized way, so you are liable to get a non-up to date value. 您没有以同步的方式访问大小,因此您有可能获取不最新的值。

You are getting 你越来越

end: 1065878
end: 2000000

The first line is from the thread that has finished its job first. 第一行来自首先完成其工作的线程。 It shouldn't be exactly 1M , because several threads are working. 它不应完全是1M ,因为有多个线程正在工作。 It's reasonable to assume that by the time one first thread finishes adding its 1M , the other has added at least one. 可以合理地假设,当第一个线程完成添加其1M ,另一个线程至少添加了一个。

The second line is always 2M (as you expected ) due to the synchronised method. 由于采用了同步方法,第二行始终为2M (如您所预期)。

I guess the first thread should execute for the exact number I wanted, no more no less. 我猜第一个线程应该针对我想要的确切数目执行,不多也不少。

Things happened in parallel. 事情并行发生。 The threads were running. 线程正在运行。 Each was trying to invoke updateList : one entered, the others waited. 每个人都试图调用updateList :一个进入,其他人等待。 There was no priority on who should be next, so the control over the method was being passed among all the workers in a rather random manner. 没有人优先考虑下一个人,因此该方法的控制权以相当随机的方式在所有工人之间传递。

I bet you are still thinking of the sequential execution :) One thread runs the whole run method, prints 1M , the other takes a 1M-sized list and adds its portion. 我敢打赌,您仍在考虑顺序执行:)一个线程运行整个run方法,打印1M ,另一个线程处理一个1M大小的列表并添加其部分。

To understand it better, add a print statement 为了更好地理解它,请添加打印声明

private void updateList(int i) {
    synchronized (myList) {
        myList.add(i);
        System.out.println(Thread.currentThread().getName() + " added " + i);
    }
}

and reduce the number of elements to add by a task to, let's say, 10 . 并减少任务要添加的元素数量,例如10

pool-1-thread-1 added 0
pool-1-thread-1 added 1
pool-1-thread-1 added 2
pool-1-thread-1 added 3
pool-1-thread-2 added 0
pool-1-thread-2 added 1
pool-1-thread-2 added 2
pool-1-thread-2 added 3
pool-1-thread-1 added 4
pool-1-thread-1 added 5
pool-1-thread-1 added 6
pool-1-thread-1 added 7
pool-1-thread-1 added 8
pool-1-thread-1 added 9
end: 14
pool-1-thread-2 added 4
pool-1-thread-2 added 5
pool-1-thread-2 added 6
pool-1-thread-2 added 7
pool-1-thread-2 added 8
pool-1-thread-2 added 9
end: 20

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM