以计数器为例:
1 、具有原子性安全问题的代码
public class Counter {
private int i=0;
private void increase() {
try {
//可以增加延迟,效果更明显
Thread.sleep(100);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
List<Thread> list = new ArrayList<>(10000);
Counter counter = new Counter();
for (int j = 0; j < 1000; j++) {
Thread thread = new Thread(() -> {
for (int m = 0; m < 5; m++) {
counter.increase();
}
},j+"");
list.add(thread);
}
for (Thread thread : list) {
thread.start();
}
try {
for (Thread thread : list) {
thread.join();
}
}catch (Exception e) {
e.printStackTrace();
}
System.out.println(counter.i);
}
}
多次执行结果
4887 4896
多次执行结果不一样,并且理想结果应该5000
2、使用循环CAS使用原子操作
public class Counter {
private AtomicInteger atomicInteger = new AtomicInteger(0);
// 使用cas自旋,满足条件时再自增
private void increase() {
for (;;) {
int i = atomicInteger.get();
//使用unsafe类的compareAndSwapInt方法,检查旧值有没有发生,如果发生变化则不交换,如果没有发生变化则交换。这个过程是原子性的,所有可以保证原子性
boolean res = atomicInteger.compareAndSet(i, ++i);
if (res) {
break;
}
}
}
public static void main(String[] args) {
List<Thread> list = new ArrayList<>(10000);
Counter counter = new Counter();
for (int j = 0; j < 1000; j++) {
Thread thread = new Thread(() -> {
for (int m = 0; m < 5; m++) {
counter.increase();
}
},j+"");
list.add(thread);
}
for (Thread thread : list) {
thread.start();
}
try {
for (Thread thread : list) {
thread.join();
}
}catch (Exception e) {
e.printStackTrace();
}
System.out.println(counter.atomicInteger.get());
}
}
3、使用JDK提供的工具类
public class Counter {
private AtomicInteger atomicInteger = new AtomicInteger(0);
public static void main(String[] args) {
List<Thread> list = new ArrayList<>(10000);
Counter counter = new Counter();
for (int j = 0; j < 1000; j++) {
Thread thread = new Thread(() -> {
for (int m = 0; m < 5; m++) {
counter.atomicInteger.incrementAndGet();
}
},j+"");
list.add(thread);
}
for (Thread thread : list) {
thread.start();
}
try {
for (Thread thread : list) {
thread.join();
}
}catch (Exception e) {
e.printStackTrace();
}
System.out.println(counter.atomicInteger.get());
}
}
4、使用锁机制实现原子操作
public class Counter {
private int i=0;
private void increase() {
try {
Thread.sleep(100);
//要尽量减少锁范围
synchronized(this) {
i++;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
List<Thread> list = new ArrayList<>(10000);
Counter counter = new Counter();
for (int j = 0; j < 1000; j++) {
Thread thread = new Thread(() -> {
for (int m = 0; m < 5; m++) {
counter.increase();
}
},j+"");
list.add(thread);
}
for (Thread thread : list) {
thread.start();
}
try {
for (Thread thread : list) {
thread.join();
}
}catch (Exception e) {
e.printStackTrace();
}
System.out.println(counter.i);
}
}