在Java中,除非存在其他操作,否则不会从其他线程更新while条件

时间:2018-08-08 20:53:04

标签: java thread-safety

我在Windows 10上使用JavaSE-1.8。我有以下意外行为。我还使用Paho Mqtt客户端,并且服务器在虚拟机中运行。

设置:

在main函数中,有一个while循环,循环直到变量terminate_by_mqtt为真。当外部客户端(例如Linux上的mosquitto_pub)将任何内容写入主题时,将设置此变量:"terminate"

以下代码按预期工作:

Main.java:

public class Main{

static Vehicle vehicle;
private static boolean terminate_by_mqtt = false;

public static void main(String[] args) {

    MqttClient client = null;

    try {
        String clientId = "ECU1";
        String broker = "tcp://192.168.56.1:1883";
        client = new MqttClient(broker, clientId);
        MqttConnectOptions connOpts = new MqttConnectOptions();
        connOpts.setCleanSession(true);
        client.connect(connOpts);
        System.out.println("Connected");
        client.subscribe("terminate");
        client.setCallback(new TopicCallback());
        terminate_by_mqtt = false;

        // ***** This while loop is the symptom ****
        while (true) {
            if(terminate_by_mqtt) break;

            // Works with flush or println. Remove this line and loop hangs
            System.out.flush();
        }
        System.out.println("loop termianted");
        System.out.println("Disconnected");
        System.out.flush(); 

    } catch (MqttException me) {

    }
    // ... Code below (or no code) does not impact the problem
}

static public  synchronized void setTermination(boolean v) {
      terminate_by_mqtt = v;
  }
}

TopicCallback.java实现MqttCallback

以下函数处理回调。请注意,这在另一个线程上运行。

@Override
public void messageArrived(String arg0, MqttMessage msg) throws Exception {
    // TODO Auto-generated method stub
    byte[] bytes = msg.getPayload();
    String x = new String(bytes, "UTF-8");
    System.out.print(x);
    System.out.flush();

 // Causes while loop to terminate if we write to "terminate" topic
    if(arg0.equals("terminate")) {
        Main.setTermination(true);
    }
}

问题:

如代码中所示,当我将标志设置为true时,有一个while循环不会终止。如果我在while循环中添加System.out.flush(),那么就没有问题。如果我删除该行,则while循环不会终止。

然后我尝试在Eclipse中调试程序。

  1. 没有断点开始
  2. 调试程序
  3. 使用外部Mqtt客户端写入"terminate"主题。
  4. 等等。程序不会终止。
  5. 将断点放在if(terminate_by_mqtt) break;行上
  6. 5点后,程序将在循环内中断,然后while循环将检查标志并中断!

我试图在循环中进行一些算术运算,但这并不能像System.out.flush()那样帮助解决问题。

好像代码在“忽略”那行,认为它不会改变(也许是由于一些优化工作?)。我不知道该如何证明/反驳。

问题:

知道发生了什么吗?

0 个答案:

没有答案
相关问题