首页 > 解决方案 > Java-Synchronized String 导致干扰

问题描述

我正在使用一个简单的程序,其中定义了 2 个线程以简单地从 10 倒数。我有一个 ThreadColor 类,只是为了能够为 2 个线程着色为不同的颜色。包 com.sherif;

public class Main {

public static void main(String[] args) {

    Countdown countdown = new Countdown();

    CountdownThread t1 = new CountdownThread(countdown);
    t1.setName("Thread 1");
    t1.start();

    CountdownThread t2 = new CountdownThread(countdown);
    t2.setName("Thread 2");
    t2.start();

    }
}

class Countdown {
private int i;
String color;

public void doCountdown() {
    switch (Thread.currentThread().getName()) {
        case "Thread 1":
            color = ThreadColor.ANSI_BLUE;
            break;

        case "Thread 2":
            color = ThreadColor.ANSI_RED;
            break;

        default:
            color = ThreadColor.ANSI_CYAN;

    }

    synchronized (color) {
        for (i = 10; i > 0; i--) {
            System.out.println(color + Thread.currentThread().getName() + "   i= " + i);
        }
      }
   }
}

class CountdownThread extends Thread {

private Countdown countdown;

public CountdownThread(Countdown countdown) {
    this.countdown = countdown;
}

@Override
public void run() {

    this.countdown.doCountdown();
    }
}

我正在同步倒计时的 for 循环以避免使用颜色对象的干扰。尽管我将颜色定义为两个线程共享的实例变量,但它仍然会产生干扰。但是,当我使用不同的字符串时,它工作得很好。我知道我可以在(this)上使用同步,但我想了解到底发生了什么。

标签: java

解决方案


您的color字段不会通过简单地在字段上同步来保护,因为更改值的赋值语句不同步。

块做的唯一事情synchronized是确保两个线程不会同时在块运行,并且只有当 的值color引用同一个对象时。

即使线程 1 已经在块内,也不会阻止线程 2 更改color字段的值。

您的代码的时间线可能是:

  • 线程 1 套color = ThreadColor.ANSI_BLUE

  • 线程 1 进入块,在ANSI_BLUE对象上同步,并开始打印。

  • 线程2套color = ThreadColor.ANSI_RED

  • 线程 2 进入块,在ANSI_RED对象上同步,并开始打印。

    如您所见,它们甚至没有在同一个对象上同步,因此两者可以同时在synchronized块内。

  • 两个胎面继续并行打印。


推荐阅读