21xrx.com
2025-06-13 12:11:10 Friday
登录
文章检索 我的文章 写文章
Java多线程可见性问题:编写可输出结果的代码
2023-07-12 12:53:29 深夜i     16     0
Java 多线程 可见性 代码 输出结果

在Java多线程编程中,一个很重要的问题是可见性问题。当多个线程同时访问一个共享变量时,如果没有采取正确的同步措施,就可能出现可见性问题。简单来说,就是一个线程修改了共享变量的值,但是其他线程并没有立刻看到这个变化。

可见性问题对程序的正确性和性能都有很大的影响。有时候,一个线程的修改会被其他线程“隐藏”很长时间,导致程序出现很奇怪的错误。为了排除这个问题,我们需要采取正确的同步措施,让所有的线程都能看到最新的值。

下面是一段简单的代码,可以演示可见性问题:

public class Demo {
  private volatile boolean flag = true;
  public void sayHello() {
    while (flag) {
      System.out.println("Hello!");
    }
  }
  public void stop()
    flag = false;
  
  public static void main(String[] args) throws InterruptedException {
    Demo demo = new Demo();
    new Thread(demo::sayHello).start();
    Thread.sleep(1000);
    demo.stop();
  }
}

这段代码定义了一个`Demo`类,其中有一个`flag`变量表示是否继续输出`Hello!`。`sayHello()`方法会不断地输出`Hello!`,直到`flag`变成`false`为止。`stop()`方法可以修改`flag`的值,让`sayHello()`方法停止输出。

在`main()`方法中,我们创建了一个线程来执行`sayHello()`方法,然后等待1秒钟,最后调用`stop()`方法来停止输出。我们希望这段代码能够正常地输出`Hello!`一段时间,然后在调用`stop()`方法后立刻停止输出。但是,实际情况并不总是如此。

如果你运行这段代码,你会发现有时候它能正常输出,有时候却不会停止。这就是可见性问题导致的结果。当我们修改了`flag`的值时,虽然它是一个`volatile`变量,但是其他线程却不一定能立刻看到这个变化。这就导致了某些情况下,`sayHello()`方法会继续输出`Hello!`,即使`flag`已经被修改成了`false`。

为了解决这个问题,我们需要采取正确的同步措施。在这个例子中,我们可以使用`synchronized`关键字来同步对`flag`变量的访问。具体来说,我们可以修改代码如下:

public class Demo {
  private boolean flag = true;
  public synchronized void sayHello() {
    while (flag) {
      System.out.println("Hello!");
    }
  }
  public synchronized void stop()
    flag = false;
  
  public static void main(String[] args) throws InterruptedException {
    Demo demo = new Demo();
    new Thread(demo::sayHello).start();
    Thread.sleep(1000);
    demo.stop();
  }
}

这个代码中,我们把`synchronized`关键字加到了`sayHello()`和`stop()`方法上面,以同步对`flag`变量的访问。这样,当一个线程修改了`flag`的值后,其他线程就能立刻看到这个变化,从而保证了这个变量的可见性。

通过这个例子,我们可以看到可见性问题在Java多线程编程中非常重要,但也不是特别容易理解和解决。我们需要不断学习和实践,才能写出正确、高效的多线程程序。

  
  

评论区