Java线程安全计数器
我正在学习编写线程安全的程序,以及如何评估非线程安全的代码 如果一个类在由多个线程执行时功能正确,则该类被认为是线程安全的 My Counter.java不是线程安全的,但是所有3个线程的输出都按预期从0到9打印 有人能解释为什么吗?线程安全是如何工作的Java线程安全计数器,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,我正在学习编写线程安全的程序,以及如何评估非线程安全的代码 如果一个类在由多个线程执行时功能正确,则该类被认为是线程安全的 My Counter.java不是线程安全的,但是所有3个线程的输出都按预期从0到9打印 有人能解释为什么吗?线程安全是如何工作的 public class Counter { private int count = 0; public void increment() { count++; } public void
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();
}
}
您的计数器不是通过3个线程共享的,相反,每个线程都有一个唯一的计数器您的代码在特定测试中运行良好。但这并不意味着它总是很好用。尝试多次迭代,您可能会看到异常 你的测试有点像,如果你测试一座桥可以支撑20辆卡车,只需驾驶一辆汽车。它没有证明什么。使用测试证明th代码是线程安全的几乎是不可能的。只有仔细阅读和理解所有潜在的问题才能保证这一点。一个非线程安全的程序可能会工作多年,突然出现错误 要使计数器安全,请使用AtomicInteger 编辑:
另外,正如@SpringRush所指出的,线程之间没有共享一个计数器。每个线程都有自己的计数器。因此,您的代码实际上是线程安全的,但我认为它并没有达到您想要的效果。因此,这实际上是线程安全的。对于每个CountThread,都有一个计数器。要使其不是线程安全的,请将计数器变量更改为:
private static Counter counter = new Counter();
那么它就不是线程安全的,因为不同的线程可能会同时修改计数器状态。尝试以下方法:
public class ThreadSafeCounter {
AtomicInteger value = new AtomicInteger(0);
public ThreadSafeCounter(AtomicInteger value) {
this.value = value;
}
public void increment() {
value.incrementAndGet();
}
public void decrement() {
value.decrementAndGet();
}
public AtomicInteger getValue() {
return value;
}
}您在每个线程中使用了不同的计数器对象,因此在本例中您没有看到任何线程安全问题。也许您应该解释为什么会出现这种情况,以便获得更彻底的答案。显而易见的,因此省略的解释是OP在每个线程中创建了一个唯一的计数器实例。当然,我会遵循推理。我只是不知道作者是否理解他放置反实例是如何使其特定于线程的+我想是的。是的,我是在发布了我答案的第一个版本后才看到的。我修复了它。换句话说,每个线程中声明的所有变量都不会受到影响?只有在多个线程之间共享某些状态时,才会出现线程安全问题。如果某个状态仅可见并被一个线程触及,则此状态不会有任何线程安全问题。确定。这是我写的一个无效的例子。