源代码:
/**
* @author: Yang Jiaheng
* @date: 2019/4/14
* @description: 多个线程对同一个属性进行操作时的并发问题。
* 但是当原子处于不稳定状态的时候,还是有可能使用原子性操作来访问他们,这个例子演示了这种情况
*/
public class AtomicityTest implements Runnable {
private int i = 0;
public int getValue() {
return i;
}
@Override
public void run() {
while (true) {
evenIncrement();
}
}
private synchronized void evenIncrement() {
i++;
i++;
}
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
AtomicityTest at = new AtomicityTest();
exec.execute(at);
while (true) {
int value = at.getValue();
if (value % 2 != 0) {
System.out.println(value);
System.exit(0);
}
}
}
}
修改后代码:
/**
* @author StivenYang
* @program interview
* @description 使用AtomicInteger解决当对象处于不稳定状态时并发产生的错误问题
* @date 2019-04-27 16:59
**/
public class AtomicIntegerTest implements Runnable {
private AtomicInteger i = new AtomicInteger(0);
public int getValue() {
return i.get();
}
@Override
public void run() {
while (true) {
evenIncrement();
}
}
private void evenIncrement() {
i.addAndGet(2);
}
public static void main(String[] args) {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
System.out.println("打断中");
System.exit(0);
}
}, 5000); //只让终端无响应5s,之后自动退出
ExecutorService exec = Executors.newCachedThreadPool();
AtomicIntegerTest ait = new AtomicIntegerTest();
exec.execute(ait);
while (true) {
int val = ait.getValue();
if (val % 2 != 0) {
System.out.println(val);
System.exit(0);
}
}
}
}
总结:
在实际情况中,应尽可能地使用现有的线程安全对象(例如:AcomicLong)来管理类的状态。与非线程安全的对象相比,判断线程安全对象的可能状态及其状态转换情况要更为容易,从而也更容易维护和验证线程安全性。