并发-原子变量类
在多线程环境中,如果多个线程对共享资源同时进行操作的话,很容易出现数据不一致的情况(如并发环境同时对库存扣除,导致余额不对),通常情况下我们会使用synchronized或者Lock同步方式来保证线程安全。
示例:对库存余额不加锁,导致余额出错。商品库存总共100,模拟了100个线程扣减库存,线程执行完后,库存余额应该为0,实际并不是,见下方示例代码。
package com.gingko.thread;
//商品信息类
public class Product {private String productName;private int inventory;//库存public Product(String productName,int inventory ) {this.productName = productName;this.inventory = inventory;}//扣减库存public void deduction() {this.inventory--;}public int getInventory() {return inventory;}
}
package com.gingko.thread;
import java.util.ArrayList;
import java.util.List;public class MultiThread {public static void main(String[] args) {Product product = new Product("iphone",100);List<Thread> threads = new ArrayList<>();for (int i = 0; i < 100; i++) {Thread thread = new Thread(() -> {try {Thread.sleep(50);//模拟扣库存时间} catch (InterruptedException e) {e.printStackTrace();}product.deduction();});threads.add(thread);}//批量开启线程for (Thread t:threads) {t.start();}//等待线程结束查看库存余额for (Thread t:threads) {try {t.join();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("库存余额是:" + product.getInventory());}
}
运行结果如下:
为了保证业务的准确性,以下2种方式都可以实现。
方式1:扣减库存方法加锁:
运行结果如下,符合预期。
方式2:通过原子变量修饰库存,使其满足线程安全
运行结果如下,符合预期。
synchronized和Atomic方式比较:
Atomic类由于使用了底层的CAS操作,通常比synchronized关键字具有更好的性能。在高并发环境下,Atomic类可以更好地支持多线程的并发操作。
synchronized关键字由于涉及到锁的获取和释放,可能会引入较大的性能开销。在某些情况下,使用synchronized可能会导致性能瓶颈。