Java 线程如何共享创建它们的同一实例的字段变量?
我想测试接口是否可运行。 创建实现可运行接口的类的实例。然后通过同一实例创建三个线程。观察线程如何共享实例的字段变量。 两个问题: 1.为什么这两个结果不像“20,19,18…1,0”的顺序? 2.为什么这两个结果彼此不同?(我运行代码两次。) 代码如下:Java 线程如何共享创建它们的同一实例的字段变量?,java,multithreading,runnable,Java,Multithreading,Runnable,我想测试接口是否可运行。 创建实现可运行接口的类的实例。然后通过同一实例创建三个线程。观察线程如何共享实例的字段变量。 两个问题: 1.为什么这两个结果不像“20,19,18…1,0”的顺序? 2.为什么这两个结果彼此不同?(我运行代码两次。) 代码如下: public class ThreadDemo2 { public static void main(String[] args) { // TODO Auto-generated method stub
public class ThreadDemo2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
TestThread tt = new TestThread();
Thread t1 = new Thread(tt);
Thread t2 = new Thread(tt);
Thread t3 = new Thread(tt);
t1.start();
t2.start();
t3.start();
}
}
class TestThread implements Runnable {
public int tickets = 20;
public void run(){
while (tickets >= 0){
System.out.println(Thread.currentThread().getName() + ":the number of tickets is " + tickets--);
}
}
}
我运行了两次代码。这两个结果如下所示。
第一次:
Thread-1:the number of tickets is 20
Thread-2:the number of tickets is 18
Thread-2:the number of tickets is 16
Thread-0:the number of tickets is 19
Thread-2:the number of tickets is 15
Thread-1:the number of tickets is 17
Thread-2:the number of tickets is 13
Thread-0:the number of tickets is 14
Thread-2:the number of tickets is 11
Thread-1:the number of tickets is 12
Thread-2:the number of tickets is 9
Thread-0:the number of tickets is 10
Thread-2:the number of tickets is 7
Thread-1:the number of tickets is 8
Thread-2:the number of tickets is 5
Thread-0:the number of tickets is 6
Thread-2:the number of tickets is 3
Thread-1:the number of tickets is 4
Thread-2:the number of tickets is 1
Thread-0:the number of tickets is 2
Thread-1:the number of tickets is 0
Thread-0:the number of tickets is 19
Thread-2:the number of tickets is 18
Thread-2:the number of tickets is 16
Thread-2:the number of tickets is 15
Thread-1:the number of tickets is 20
Thread-2:the number of tickets is 14
Thread-2:the number of tickets is 12
Thread-2:the number of tickets is 11
Thread-0:the number of tickets is 17
Thread-2:the number of tickets is 10
Thread-2:the number of tickets is 8
Thread-1:the number of tickets is 13
Thread-1:the number of tickets is 6
Thread-1:the number of tickets is 5
Thread-2:the number of tickets is 7
Thread-0:the number of tickets is 9
Thread-2:the number of tickets is 3
Thread-1:the number of tickets is 4
Thread-2:the number of tickets is 1
Thread-0:the number of tickets is 2
Thread-1:the number of tickets is 0
第二次:
Thread-1:the number of tickets is 20
Thread-2:the number of tickets is 18
Thread-2:the number of tickets is 16
Thread-0:the number of tickets is 19
Thread-2:the number of tickets is 15
Thread-1:the number of tickets is 17
Thread-2:the number of tickets is 13
Thread-0:the number of tickets is 14
Thread-2:the number of tickets is 11
Thread-1:the number of tickets is 12
Thread-2:the number of tickets is 9
Thread-0:the number of tickets is 10
Thread-2:the number of tickets is 7
Thread-1:the number of tickets is 8
Thread-2:the number of tickets is 5
Thread-0:the number of tickets is 6
Thread-2:the number of tickets is 3
Thread-1:the number of tickets is 4
Thread-2:the number of tickets is 1
Thread-0:the number of tickets is 2
Thread-1:the number of tickets is 0
Thread-0:the number of tickets is 19
Thread-2:the number of tickets is 18
Thread-2:the number of tickets is 16
Thread-2:the number of tickets is 15
Thread-1:the number of tickets is 20
Thread-2:the number of tickets is 14
Thread-2:the number of tickets is 12
Thread-2:the number of tickets is 11
Thread-0:the number of tickets is 17
Thread-2:the number of tickets is 10
Thread-2:the number of tickets is 8
Thread-1:the number of tickets is 13
Thread-1:the number of tickets is 6
Thread-1:the number of tickets is 5
Thread-2:the number of tickets is 7
Thread-0:the number of tickets is 9
Thread-2:the number of tickets is 3
Thread-1:the number of tickets is 4
Thread-2:the number of tickets is 1
Thread-0:the number of tickets is 2
Thread-1:the number of tickets is 0
这是多线程程序的正常行为。instatnt上只能有有限数量的线程获得CPU,具体取决于处理器的容量。在多线程环境中,每个线程都有cpu时间,这个顺序可能是连续的,也可能不是连续的 您可以使用“synchronized”语句进行顺序处理。虽然此程序用于显示多线程的强大功能,而使用同步会扼杀实际用途,但在某些情况下需要同步,例如访问共享资源 以下是赫伯特·席尔德的完整参考资料中的几行 Java被设计为在广泛的环境中工作。一些 这些环境中的大多数实现多任务的方式与其他环境根本不同。对于 安全性方面,共享相同优先级的线程应该偶尔产生一次控制。这 确保所有线程都有机会在非强制操作系统下运行。 实际上,即使在非抢占性环境中,大多数线程仍然有机会运行, 因为大多数线程不可避免地会遇到一些阻塞情况,比如等待 I/O。发生这种情况时,阻塞的线程被挂起,其他线程可以运行。但是 如果您想要平滑的多线程执行,最好不要依赖它。也, 某些类型的任务是CPU密集型的。这样的线程控制着CPU 一个线程可以有五种状态。
当一个线程正在运行时,所有其他线程都在争夺CPU。任何线程(根据优先级)都可以获得CPU。因此,顺序不一定是连续的。这就是为什么每次运行都会得到随机输出。这就是多线程。线程分别调度到处理器上,甚至可以在不同的CPU核上以真正的并行方式运行(如果您有多核处理器)。 这就是为什么这两次运行会产生不同的结果:线程调度的方式取决于当前环境,而当前环境还包括系统中的其他进程 线程执行可能以各种方式交错,来自不同线程的
println
到达单个输出日志的顺序也可能不同。一个线程可能已递减计数器,但在写入输出日志之前,其他线程可能同时执行了其他操作。在第一个线程有机会写入较旧的值之前,其他线程甚至可能已经递减并写入了较新的值。这些都是可能的和有效的交错,这就是为什么您可能无法在输出中获得递减顺序
见鬼,如果您使用更多线程进行更多测试,您甚至可能会看到相同的值从两个不同的线程弹出两次!这是因为两个线程可能同时尝试读取或写入
tickets
字段,导致它们都读取相同的值。存在各种有趣的并发问题,这就是为什么需要同步机制(如锁、信号量或原子更新)来获得正确的行为。欢迎来到令人惊叹的并行处理世界。在使用线程时,除非您使用诸如锁和屏障之类的同步机制,否则没有人能够保证如何安排线程的进度
这里您要做的是打印一个统一的输出流,应该显示线程的进展情况。这意味着您正在合并来自线程的打印输出,但您无法判断这些打印是如何交叉的。此外,打印不一定按照调用函数的顺序进行,有几层缓冲,更糟糕的是,对打印代码的实际调用不是通过读取和减量自动完成的
您可以说变量被重复递减(尽管由于它没有使用任何原子/同步机制,您甚至不能确定不会看到重复的结果和递减被覆盖),并且每个线程在打印较低的值之后不会打印较高的值,而是在线程之间,这些消息可能会被暂停,从而导致打印顺序错误
当您在第一个示例中看到-
Thread-2:the number of tickets is 16
Thread-0:the number of tickets is 19
线程0实际上首先读取并递减变量,但打印延迟(由于上下文切换或其他原因)。线程2在其他几个实例之后运行,但立即打印了它的消息,只有到那时线程0才能完成之前的实例。请注意,这里没有看到线程0在打印中间的任何其他值,它的下一次迭代已经读取14 编辑: 为了进一步阐述,这里有一个可能的交错的小例子 假设每个线程的机器代码是-(以虚构的伪格式) (var是一个内存位置,位于堆栈上,例如) 假设有两个线程在运行。一种可能的交织可以是——
thread 0 | thread 1
------------------------------------
load [var] -> rax | // reads 20
dec rax |
store rax -> [var] |
| load [var] -> rax // reads 19
| dec rax
| store rax -> [var]
| call print function // prints 19
| cmp rax, 0
| jg label
call print function | //prints 20
cmp rax, 0 |
jg label |
这有点过于简单化,但它显示了如何将值按顺序打印出来。只要在同一线程内保持顺序,任何交织都是可能的
还要注意的是,您可以有
thread 0 | thread 1
------------------------------------
load [var] -> rax | // reads 20
dec rax |
| load [var] -> rax // reads 20 again !!!
| dec rax
| store rax -> [var]
store rax -> [var] |
...
在这种情况下,您将得到20个打印两次。因此您有三个线程,所有线程都处理一个变量。我想这是有意的 这是