简体   繁体   English

Java线程运行

[英]Java thread run

I have code like this 我有这样的代码

  boolean start = false;
  ThreadX a = new ThreadX();
  a.start();
  start = true;

  Class ThreadX extends Thread {

          public void run() {
              while (start == true) {
                ...
              }

          } 
  }

Is there a problem with this code? 这段代码有问题吗? I have executed this and did not see any issue just wanted to get a hang whether the thread will start and never execute start = true 我已经执行了这个,没有看到任何问题只是想挂掉线程是否将启动并且永远不执行start = true

There are two problems: 有两个问题:

  • Firstly the thread could in theory start before start is ever set to true, and thus terminate immediately. 首先,线程在理论上可以在将start设置为true之前start ,然后立即终止。
  • Secondly the thread could in theory start after start is set to true, but never set the value of start change (assuming it's being set to false somewhere in the original thread) due to a lack of memory barriers. 其次,理论上线程可以在start设置为true之后start ,但是由于缺少内存屏障,因此从不设置start change的值(假设在原始线程的某处设置为false)。 Either make the variable volatile, use locks, or use one of the AtomicXXX types in java.util.concurrent.atomic, eg AtomicBoolean . 将变量AtomicXXX volatile,使用锁或使用java.util.concurrent.atomic中的AtomicXXX类型之一,例如AtomicBoolean

Also for good practice you should implement Runnable instead of extening Thread - you don't want to change the fundamental behaviour of a thread, you just want to provide it a task. 也很好的做法应实现Runnable ,而不是extening Thread -你不想改变线程的基本行为,你只是想提供它的任务。 (The fact you can extend thread to do this is a design flaw IMO.) (事实上​​,您可以扩展线程来执行此操作是IMO的设计缺陷。)

Yes, there is a problem. 是的,有问题。

Assuming that start is a local variable, this code will not even compile, since all local variables that are used in inner classes have to be final . 假设start是一个局部变量,该代码甚至都不会编译,因为内部类中使用的所有局部变量都必须是final

Assuming that start is a field of some class. 假设start是某个领域的领域。 Then the field must be declared volatile , otherwise it is not guaranteed that if one thread changes the variable, the other threads will see that change. 然后必须将该字段声明为volatile ,否则不能保证如果一个线程更改了变量,其他线程将看到该更改。

It depends if start becomes true before or after run() begins. 这取决于在run()开始之前或之后start变为true。 I say "it depends" because there is no guarantee by the JVM that either will be the case. 我说“这取决于”,因为JVM不能保证情况会如此。 This is, of course, assuming that start is within scope of the instance of your thread. 当然,这是假设start在线程实例的范围内。

with this it is not guaranteed that the loop will ever enter: 这样就不能保证循环会进入:

if the thread is started and the current thread (the thread starting the other one) is interrupted so the other thread can run the while condition will be false and the run will exit 如果启动了该线程,并且当前线程(启动另一个线程的线程)被中断,则另一个线程可以运行,而while条件为false且运行将退出

on the other hand if the current thread is not interrupted and set start to true the loop will enter 另一方面,如果当前线程未中断并且将start设置为true,则循环将进入

this is known as a race condition 这被称为比赛条件

The thread will start, but might exit immedietly, exit later, or run forever: 该线程将启动,但可能会立即退出,稍后退出或永远运行:

Scenario 1 - run forever before thread run() enters, start is updated to true and the jvm decides to write it to the memory so the created thread will see it as true and will never terminate. 场景1-永远运行直到线程run()进入之前,start更新为true,并且jvm决定将其写入内存,以便创建的线程将其视为true,并且永远不会终止。

Scenario 2 - exit immediately before run() starts the start is updated to true but the jvm don't update physical memory (no membar), then run continues and sees false, and will terminate, or the run() and the loop runs for the first before start=true is run. 场景2-在run()开始之前立即退出,将start更新为true,但是jvm不更新物理内存(无内存),然后继续运行并看到false,然后终止,或者run()和循环运行在start = true运行之前的第一个。

Scenario 3 - exit at some point before run() or after run() start is updated but the jvm updates the physical memory at some point after run do a number of iterations. 场景3-在更新run()之前或运行run()开始之后的某个时刻退出,但是jvm在运行多次迭代后的某个时刻更新物理内存。

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

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