我正在尝试使用方法上的同步与原子变量(java.util.concurrent.atomic包)进行Java多线程。
以下是课程:
// Interface ICounter.java
public interface ICounter {
public void increment();
public void decrement();
public int value();
}
// Class Counter.java
public class Counter implements ICounter {
private int c = 0;
@Override
public void increment() {
c++;
}
@Override
public void decrement() {
c--;
}
@Override
public int value() {
return c;
}
}
// Class AtomicCounter.java
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicCounter implements ICounter {
private AtomicInteger c = new AtomicInteger(0);
@Override
public void increment() {
c.incrementAndGet();
}
@Override
public void decrement() {
c.decrementAndGet();
}
@Override
public int value() {
return c.get();
}
public long getIncrement() {
return c.incrementAndGet();
}
}
// Class MainProg.java
public class MainProg {
public static void main(String args[]) {
ICounter counter = new AtomicCounter();
//ICounter counter = new SynchronizedCounter();
Thread thread1 = new Thread(new CountRunner(counter));
Thread thread2 = new Thread(new CountRunner(counter));
thread1.start();
thread2.start();
}
}
class CountRunner implements Runnable {
private ICounter counter;
public CountRunner(ICounter counter) {
this.counter = counter;
}
public void run() {
while (true) {
counter.increment();
System.out.println(Thread.currentThread().getName() + " count=" + counter.value());
System.out.println("-------------------");
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
运行Atomic或Synchronized的结果不显示变量integer是线程安全的,例如:
Thread-0 count=1
-------------------
Thread-1 count=2
-------------------
Thread-0 count=3
-------------------
Thread-1 count=4
-------------------
Thread-0 count=5
-------------------
Thread-1 count=6
-------------------
Thread-0 count=7
-------------------
Thread-1 count=8
-------------------
Thread-0 count=10
-------------------
Thread-1 count=10
-------------------
从结果中,最后两行显示2个线程正在访问计数器类的整数变量的相同值。 也许我在这里错过了什么?
谢谢!
答案 0 :(得分:4)
因为您的counter.increment()
和System.out.println
不是一个原子动作。
Thread 1 Thread2
increment
increment
System.out.println // print 10
System.out.println
// print 10 too
答案 1 :(得分:4)
您只需一步递增值,然后在另一步中获取值。虽然这些单独的步骤中的每一个都被基础AtomicInteger
类保证为原子,但是您进行两次单独操作的事实会使您在print语句中看到的值受到线程执行顺序的影响。
为了能够准确显示给定线程更新的值,您需要在getIncrement()
方法执行的单个操作中更新并获取结果值。能给你预期结果的代码如下所示:
int changedValue = counter.getIncrement();
System.out.println(Thread.currentThread().getName() + " count=" + changedValue);
答案 2 :(得分:2)
您错过的是您的AtomicCounter
类确实正常工作,并且由于线程在调用.increment()
和.value()
之间切换而发生了观察到的行为:
-------------------
Thread-0 increment -> value = 9
-------------------
Thread-1 increment -> value = 10
-------------------
Thread-0 print value <- 10
-------------------
Thread-1 print value <- 10
-------------------