繁体   English   中英

Java中的多线程并发

[英]Concurrency in multithreading in java

我正在为ocjp 6考试进行模拟考试,并发访问遇到以下问题:

public class Cruiser {
   private int a = 0;

    public void foo() {
        Runnable r = new LittleCruiser();
        new Thread(r).start();
        new Thread(r).start();
    }

    public static void main(String arg[]) {
        Cruiser c = new Cruiser();
        c.foo();
    }

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

可能的输出是什么?

选项:

A)0、2、4、0、2、4、6、6

B)0、2、4、6、8、10、12、14

C)0、2、4、6、8、10、2、4

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

E)0、2、4、6、8、10、12、14、0、2、4、6、8、10、12、14

答案是A和B。

我的疑问是,选项A如何成为可能的输出? 我的意思是,如果第一个线程进入它的run方法,它将更改a的值,如果在第二个线程之间出现,它将获取a的更改后的值,那么数字如何重复? 请解释这个问题,在此先感谢!

这是一种可能的情况,其中:

  • 列a是a的值。
  • 线程1是线程1的动作
  • 第一个电流是线程1的电流值
  • 线程2是线程2的动作
  • 第二电流是线程2的电流值

步骤如下:

a        Thread 1     current     Thread 2    current
----------------------------------------------------------
0        current = 0     0 
0                                 current = 0    0
0        current = a     0
0                                 current = a    0
0        print curr      0                                // Prints 0
2        a = current+2   0
2        current = a     2
2        print current   2                                // Prints 0, 2
4        a = current+2   2
4        current = a     4
4        print current   4                                // Prints 0, 2, 4
4                                 print current  0        // Prints 0, 2, 4, 0
2                                 a = current+2  0
2                                 current = a    2
2                                 print current  2        // Prints 0, 2, 4, 0, 2
4                                 a = current+2  2
4                                 current = a    4
4                                 print current  4        // Prints 0, 2, 4, 0, 2, 4
6                                 a = current+2  4 
6        a = current+2    4
6                                 current = a    6
6        current = a      6
6        print current                                     // Prints 0, 2, 4, 0, 2, 4, 6
6                                 print current            // Prints 0, 2, 4, 0, 2, 4, 6, 6

请注意,这不是唯一可能的方案,因为某些操作可以在线程1和线程2之间反转(例如,最后两对)

我的意思是,如果第一个线程进入它的run方法,它将改变a的值

如果在第二个线程之间,它将获得a的更改值

不确定,更新后的值可能对第二个线程不可见。 请参阅内存一致性

假设定义并初始化了一个简单的int字段:

int counter = 0;

计数器字段在两个线程A和B之间共享。

假设线程A递增计数器:

counter++;

然后,不久之后,线程B打印出计数器:

System.out.println(counter);

如果两个语句已在同一线程中执行,则可以安全地假定打印出的值为“ 1”。 但是,如果两个语句在单独的线程中执行,则打印出的值很可能是“ 0”,因为不能保证线程A对计数器的更改将对线程B可见-除非程序员已在两者之间建立事前发生的关系这两个陈述

如果没有比赛条件,答案将始终为B),因为您增加了相同的变量。 但是事实并非如此,因为在这段代码中:

 current = a;
 System.out.print(current + ", ");
 a= current + 2;

您设置current = a(具有一些值),将其用于打印,但是在此期间,另一个线程可能已经修改了a。 然后,当您设置a = current + 2时,您将覆盖其他线程的更改。

例如,如果步骤为:最初a = 0;

  1. 线程1 current = a; (T1电流= 0)
  2. 线程2 current = a; (t2电流也= 0)
  3. 线程1打印当前-> 0
  4. 线程1设置a = current + 2-> a = 2;
  5. 线程2打印自己的电流,该电流仍为步骤2中设置的0
  6. 线程2设置a = current + 2-> a = 2基本上覆盖了另一个线程中发生的步骤4

因此,您也可以获得其他可能的答案,例如:

0、0、2、4、6、2、4、6

0、2、4、6、0、2、4、6

0、2、4、0、2、4、6、6等

这取决于线程的执行方式以及在将电流设置为某值然后再设置为current + 2时之间发生的情况

暂无
暂无

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

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