Java线程安全计数器

ilo*_*arn 0 java multithreading thread-safety

我正在学习编写线程安全的程序以及如何评估非线程安全的代码.

如果一个类在由多个线程执行时正常运行,则该类被认为是线程安全的.

我的Counter.java不是一个线程安全的,但输出是按照预期从0到9打印的所有3个线程.

谁能解释为什么?以及线程安全如何工作?

public class Counter {

    private int count = 0;

    public void increment() {
        count++;
    }

    public void decrement() {
        count--;
    }

    public void print() {
        System.out.println(count);
    }

}

public class CountThread extends Thread {
    private Counter counter = new Counter();

    public CountThread(String name) {
        super(name);
    }

    public void run() {
        for (int i=0; i<10; i++) {
            System.out.print("Thread " + getName() + " ");
            counter.print();
            counter.increment();
        }
    }

}

public class CounterMain {

    public static void main(String[] args) {
        CountThread threadOne = new CountThread("1");
        CountThread threadTwo = new CountThread("2");
        CountThread threadThree = new CountThread("3");

        threadOne.start();
        threadTwo.start();
        threadThree.start();
    }

}
Run Code Online (Sandbox Code Playgroud)

Bla*_*ker 9

Counter不是通过3个线程共享,而是每个线程都有唯一的Counter


JB *_*zet 5

您的代码在特定测试中运行良好.这并不意味着它总能正常工作.尝试迭代很多次,你可能会开始看到异常.

您的测试有点像,如果您测试过一座桥可以通过搭载一辆汽车在桥上支撑20辆卡车.它没有展示任何东西.并且使用测试证明代码是线程安全的几乎是不可能的.只有仔细阅读和理解所有潜在的问题才能保证.一个非线程安全的程序可能会工作多年,并突然有一个bug.

为了使您的计数器安全,请使用AtomicInteger.

编辑:

另外,正如@SpringRush所说,你不是在线程之间共享一个计数器.每个线程都有自己的计数器.因此,您的代码实际上是线程安全的,但我认为它不会按照您的意图执行.