Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的线程同步问题_Java_Multithreading_Runnable_Executorservice - Fatal编程技术网

Java中的线程同步问题

Java中的线程同步问题,java,multithreading,runnable,executorservice,Java,Multithreading,Runnable,Executorservice,我很清楚,这可能被认为是重复的,但是考虑到我的问题,我在这里找到了很多答案,我无法找到解决方案 我将runnable与多个线程共享的对象同步,并显式同步了我在内部使用的方法,但程序的结果总是3000 我尝试锁定计数器类,但它不会改变任何事情。 有人能解释一下为什么我的动作在这个例子中都不起作用吗 publicstaticvoidzad3(){ var counter=新计数器(); var toRun=new Runnable(){ @凌驾 公开募捐{ 已同步(计数器){ 对于(变量i=0;i

我很清楚,这可能被认为是重复的,但是考虑到我的问题,我在这里找到了很多答案,我无法找到解决方案

我将runnable与多个线程共享的对象同步,并显式同步了我在内部使用的方法,但程序的结果总是3000

我尝试锁定
计数器
类,但它不会改变任何事情。 有人能解释一下为什么我的动作在这个例子中都不起作用吗

publicstaticvoidzad3(){
var counter=新计数器();
var toRun=new Runnable(){
@凌驾
公开募捐{
已同步(计数器){
对于(变量i=0;i<1000;i++){
计数器。添加(1);
}
}
}
};
var t1=新螺纹(toRun);
var t2=新螺纹(toRun);
var t3=新螺纹(toRun);
t1.start();
t2.start();
t3.start();
试一试{
t1.join();
t2.连接();
t3.join();
}捕捉(中断异常e){
e、 printStackTrace();
}
System.out.println(“counter=“+counter.getCount());
}
公共类计数器{
受保护的长计数=0;
公共同步作废添加(长值){
计数=数值;
}
公共长getCount(){
返回计数;
}
}
编辑: 正如所建议的,问题在于每个线程持续运行
1000次
循环。
我的解决方案:

var toRun=new Runnable(){
@凌驾
公开募捐{
已同步(计数器){
对于(var i=counter.getCount();i<1000;i++){
计数器。添加(1);
}
}
}
};

您已经围绕“counter”变量同步了完整的for循环,这意味着每个线程将运行一次块。3 X 1000=3000

每个线程将执行一次此块

 for (var i = 0; i < 1000; i++) {
                        counter.add(1);
 }
for(变量i=0;i<1000;i++){
计数器。添加(1);
}
更新:根据您的评论判断,您希望中断1000个示例代码可以是:

 t1.start();
 t2.start();
 t3.start();

while(counter.getValue()<1000) {
    Thread.sleep(20)
}
t1.start();
t2.start();
t3.start();

虽然(counter.getValue(),但问题是您让每个线程尝试1000个增量,因此您需要这样的内容:

while (counter.getCount() < 1000) {
     counter.add(1);
}

请注意,像这样递增一个变量,的速度很慢。。您只需执行1000次,但尝试使用10亿次。事实上,3线程版本需要(在我的电脑上)1m17s,而一个简单的顺序循环需要约1.2秒。您可以通过在线程之间分配工作负载,让它们在具有独占权限的本地计数器上工作,然后最终添加结果来解决此问题。

您期望得到什么结果?@Jeppe当我试图实现
1000
时,结果总是
3000
>。然后您应该限制循环在运行时使用
计数器.getCount()<1000
,而不是
i
。这意味着两个操作必须是原子操作(读取,然后写入),(如果删除循环周围的同步)。如果你有3个线程,每个线程递增1000倍,你为什么期望结果是1000?@Jeppe是的,这很有道理。谢谢你!我明白了,但是有没有一种方法可以将
1000
分割成两个线程?因为这就是我练习的目的,我需要使用for循环来完成它。@bart kosmala我不明白老实说,你想说什么。解释更多。你已经回答了我的问题,我会将其标记为已接受。我的修复将在编辑的问题中。没有最好的解决方案。有许多解决方案,都取决于具体情况。在你的情况下,最好的解决方案是根本不使用线程:)或者选择一个多线程选项并解释它解决了什么问题。在我的机器上,使用
N=1\u 000\u 000L
顺序解决方案需要
0m1.181s
,而使用线程本地计数器的8线程解决方案需要
0m0.208s
。这取决于问题,可能并不总是能够在本地运行线程。一般来说,你应该考虑一个解决方案的性能,因为N增加了无穷大。
while (counter.getCount() < 1000) {
     counter.add(1);
}
while (true) {
    synchronized (counter) {
        if (counter.getCount() < 1000) {
            counter.add(1);
        } else {
            break;
        }
    }
}