当前位置: 首页 > 知识库问答 >
问题:

程序不总是终止吗?[重复]

郏实
2023-03-14

我想为我的一个项目测试多线程,试图开发一个解决方案,以防出现问题。

所以我做了一个小测试:

public class main
    {

        static int addToCounter;
        static int addToErrorCounter;
        public static void main(String[] args) throws InterruptedException
            {
                int threads = 10;
                Executor exec = new Executor();
                for (int i = 0; i < threads; i++)
                    {
                        double error = Math.random();
                        testClass aldo = new testClass();
                        Thread thread = aldo.getThread(300, error);
                        exec.execute(thread);
                    }
                while (threads != (addToCounter + addToErrorCounter))
                    {
                        System.out.println("Not all threads finished, number of finished threads is: " + (addToCounter + addToErrorCounter));
                        Thread.sleep(50);
                    }
                System.out.println("Number of Threads that finished correctly: " + addToCounter);
            }

    }
import test1.main;

public class testClass
    {

        public Thread getThread(long time, double error)
            {
                Thread thread = new Thread()
                    {

                        public void run()
                            {
                                try
                                    {
                                        Thread.sleep(time);
                                    }
                                catch (InterruptedException e)
                                    {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                    }

                                if (error > 0.5)
                                    {
                                        main.addToErrorCounter++;
                                        throw new java.lang.Error("HELLO");
                                    }
                                System.out.println("I DID THIS!");
                                main.addToCounter++;
                            }
                    };

                return thread;

            }

    }

(您必须修复导入,我还使用自定义类Executor,尽管这只是ExecutorService的包装)

奇怪的是,有时它工作正常,有时则不正常(终止线程总数为9,尽管我可以清楚地看到它打印了“我做到了!”误差正好是10倍)。

任何修复?

共有2个答案

况野
2023-03-14

我猜后缀操作符(main.addToCounter)不是原子的。这行代码可能相当于:

int temp = main.addToCounter;
main.addToCounter = temp + 1;
return temp;

当多个线程同时执行此操作时,两个线程可能会获得相同的temp值(因为两个线程都在执行第二个线程之前形成上述伪代码的第一行),因此一旦所有线程完成,计数器总数将太小。明白为什么我不是原子吗?了解更多信息。

这种情况下的一个快速修复方法是将addToCounter设置为原子整数,然后使用addToCounter。incrementAndGet()代替addToCounter

步博艺
2023-03-14

问题可能是赛车状态。“”运算符不是原子运算符。想象一下下面的场景。同时有两条线。两人都想增加一个数字并完成。该数字的初始值为0。线程0读取数字,现在知道它是0。线程1读取数字,现在知道它是0。线程0(知道它是0)现在将1写入内存。线程1不知道这个数字已经改变了,并且仍然相信这个数字是0,所以他还将1写入内存。

你需要一个同步机制,一个锁,一个信号灯或其他东西。

有关更多信息,请查看以下内容:http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/

对于您的示例,您可以使用该链接中的“synchronized”示例。

向主类添加一个如下所示的方法,以增加addToCounter,并向addToErrorCounter添加一个方法,以消除错误计数器的影响:

synchronized AddToError(int e){
    addToError += e;
}
synchronized IncCounter(){
    addToCounter++;
}

在测试类中调用线程中的那些方法,而不是不同步地递增它们。

 类似资料:
  • 问题内容: 我使用Hibernate创建了一个程序。 程序到达主要功能端,但是程序正在运行。 我不知道使用Hibernate 4.x版进行配置时是否会发生这种情况。 配置方式错误吗? manual1_1_first_hibernate_apps.java 实用程序 程序终止并使用buildSessionFactory方法时,以下控制台日志片段。 但是,如果不使用已弃用的buildSessionFa

  • 问题内容: 我找到了终止(关闭或停止)Java程序的方法。我找到了两个解决方案。 使用 return; 当我想退出或终止程序执行时,添加它。 使用 System.exit() ; 有时我用它。我从This Question中了解了 Sytem.exit()。 所以,我对他们都了解一点。但是我仍然对它们的实际工作方式感到困惑。请检查以下代码… 我确定 2不会出现。我想知道为什么或其他代码可以在的语句

  • 在linux中,当主线程终止时,整个过程都会退出,不管它是以何种方式终止的,都是通过函数out()或从main返回。如果主线程从main()返回,它将返回到称为crt. o或类似的“C运行时”。在crt. o中,它的c代码是这样的:退出(main(argc, argv));退出()将由主线程 最终调用,结果,所有线程都终止。 我的想法正确吗? 如果在crt中。o exit()被诸如void thr

  • 问题内容: 如何使多线程python程序响应Ctrl + C键事件? 编辑: 代码是这样的: 我试图在所有线程上删除join(),但仍然无法正常工作。是否因为每个线程的run()过程中的锁段? 编辑: 上面的代码应该可以工作,但是当当前变量在5,000-6,000范围内并遍历以下错误时,它总是会中断 问题答案: 在启动主线程之前,将除主线程之外的每个线程都设为守护进程(在2.6或更高版本中,在2.

  • 我尝试构建一个GUI应用程序,从相机抓取帧并在Tkinter GUI中显示它们。Tkinter mainloop在主线程中执行,而gui的帧抓取和更新在单独的线程中进行。 下面的代码作为一个视频流被抓取并正确显示在我的gui窗口中。但是,当我通过单击“x”来调用on_close()方法来关闭gui时,gui将关闭,但程序不会完全终止。最后一次CLI输出将为“Mainloop stopped!”,但

  • 问题内容: 这似乎是一个是或否的问题,我希望可以在某个地方回答它,但我当然找不到。Java中的内存泄漏发生的频率不如使用C或C ++这样的语言开发时发生的频率高,但是它们可以发生。 除某些情况(如共享内存)外,大多数操作系统都会清除程序终止时分配的内存。当JVM退出时,这仍然适用吗?如果我无意间在Java中创建了内存泄漏,JVM,Linux或Windows OS都可以解决吗? 问题答案: 是的,J