[英]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: 否,原因如下:
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.