您如何思考和预测这样的线程问题的输出?

Bad*_*est 9 java multithreading

我正在准备SCJP,多线程一直是我最讨厌的领域,主要是因为我不知道如何查看多线程代码并完成它.到目前为止,我的方法是用英语写下每个线程中可能发生的事情,并测试一些线程随机相互交叉的情况,这是一个非常重要且耗时且耗时的方法.所以我想看看专业人士会怎么做.你是否愿意阅读下面的代码(这是给我带来麻烦的最新问题)并记下你脑子里的内容(只有代码相关的东西,请:),当你计算出可能的输出时?问题附带的选择是最终的.我正在寻找的不是我所拥有的解决方案,而是如何在考试中有效地达到解决方案.

是的,我知道这个问题没有一个确切的答案等等.接受投票的答案最明确,最容易模仿,好吧:)

感谢大家!

问题:这些答案中哪一个是可能的输出?

public class Threads1 {

    int x = 0;

    class Runner implements Runnable {

        public void run() {
            int current = 0;
            for (int i = 0; i < 4; i++) {
                current = x;
                System.out.print(current + ", ");
                x = current + 2;
            }
        }
    }

    public static void main(String[] args) {
        new Threads1().go();
    }

    public void go() {
        Runnable r1 = new Runner();
        new Thread(r1).start();
        new Thread(r1).start();
    }
}
Run Code Online (Sandbox Code Playgroud)

选择(选择所有适用的选项):

A. 0,2,4,4,6,8,10,6,

B. 0,2,4,6,8,10,2,4,

C. 0,2,4,6,8,10,12,14,

D. 0,0,2,2,4,4,6,6,8,10,10,10,12,12,14,14,

E. 0,2,4,6,8,10,12,14,0,2,4,6,8,10,12,14,

Ber*_*t F 11

A和C (假设问题是这些答案中哪些是可能的输出?)

当然,困难的部分不是当你找到可能的解决方案时.而是,它看起来在努力,你认为是那些没有可能,并试图说服自己,你已经有了一个坚实的理由为什么它不可能你已经消灭了所有来解决你的理由的方式.

到目前为止,我的方法是用英文写下每个帖子中可能发生的事情......

你需要找出每个数字打印的线程.下面是我能想到的最有效,最简洁的格式,并且可以在您处理各种可能性时轻松地进行交叉/擦除/写入.实现:

  • 一旦找到可能的答案继续前进.如果它不可能在现实世界中或者可能存在其他可能的(或不可能的)组合并不重要.只要你找到了1种可能性,那就是你需要继续前进的全部内容.

  • 首先尝试最简单的方法,例如假设T1为每个数字,直到你击中一个不能为T1的数字,所以你填写T2,依此类推.希望你到底没有矛盾(或者是矛盾的是容易解决).一旦找到可能的组合,继续前进.

  • 随意跳过以快速消除可能的,以便您可以专注于可能不可能的.

这是我的草稿纸/工作表的最终编辑(附加了我的心理注释):

A. 0, 2, 4, 4, 6, 8, 10, 6,
   1  1  1  2  2  2   2  1     <- possible threads that produced this output - possible solution

B. 0, 2, 4, 6, 8, 10, 2, 4,
   1  2  2  2  2   ?  1        <- to print second '2', T1 interrupted between L10/L11; 4 passes of T2 used up

C. 0, 2, 4, 6, 8, 10, 12, 14,
   1  1  1  1  2   2   2   2   <- possible solution - simplest solution (T2 waits until T1 is completely done) - doesn't matter that it isn't likely, just that is possible

D. 0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14,
   1  2  1  2  1  2  1  2  1  2   ?    <- threads used up

E. 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14,
   1  1  1  1  2   2   2   2  ?   <- threads used up
Run Code Online (Sandbox Code Playgroud)

注意:

http://download.oracle.com/javase/tutorial/essential/concurrency/atomic.html

  • 读取和写入对于引用变量和大多数原始变量(除long和double之外的所有类型)都是原子的.
  • ...

原子动作不能交错,因此可以使用它们而不必担心线程干扰.


lin*_*r27 5

我对多线程问题的处理方法是分解线程将运行的代码,然后确定将运行该代码的线程数以及访问其他线程可能使用的任何变量.

在该示例中,有3个线程.该main线程调用new Threads1().go();,创建r1,并启动2个线程,new Thread(r1).start();new Thread(r1).start();.现在我们知道有多少线程可以跟踪它们将要执行的操作.

main线是要死它返回后go().

其他2个线程都将进入对象的run()方法Runner,r1.现在我们也知道每个线程都会执行run().那么让我们来看看是做什么的run().它有一个for循环,每次执行循环时都会打印输出.因此调用run()将打印4时间.所以每个线程2个线程将打印4时间.因此输出不能超过8数字.

关于那些数字将是不可能的,因为Runner每个线程的实例都是相同的,x变量可以根据同时调用的另一个线程而改变run().因此,您需要确定的是,数字序列是否可能?这个问题的答案对于A和C来说是'是'.这是因为你不知道每个线程何时会被另一个线程抢占,因为在循环中有一个本地副本正在制作,你可以得到一些非常独特的订单.

如下面SB所述,选项B即使它有8个输出也是不可能的.尝试并提出一个线程序列来创建该输出.

  • B怎么回事? (2认同)