原子类AtomicInteger介绍

java里面运算操作,如果不进行同步操作,在多线程环境下就是线程不安全的,如果你开启100个线程执行num ++,结果可想而知,每次执行的结果都不一样,代码如下:

package com.loan.common.utils;

/**
 * @author herman
 * 
 */
public class AtomicIntegerTest1 {
	public static int num = 0;
	public static void main(String[] args) {
		for (int i = 0; i < 100; i++) {
			new Thread() {
				@Override
				public void run() {
					for (int j = 0; j < 100; j++) {
						try {
							sleep(100);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						System.out.println(num++);
					}
				}; 
			}.start();
		}
	}

}

那么 用了AtomicInteger类后会变成什么样子呢?改造之后代码如下:

package com.loan.common.utils;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author herman
 *
 */
public class AtomicIntegerTest1 {
	public static AtomicInteger num = new AtomicInteger(0);
	public static void main(String[] args) {
		for (int i = 0; i < 100; i++) {
			new Thread() {
				@Override
				public void run() {
					for (int j = 0; j < 100; j++) {
						try {
							sleep(100);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						System.out.println(num.getAndIncrement());
//						System.out.println(num.incrementAndGet());
					}
				}; 
			}.start();
		}
	}

}

看代码里面注释了一句,incrementAndGet(),测试得知num.getAndIncrement()返回9999,

num.incrementAndGet()返回10000,为什么呢?

两个方法都是 以原子方式将当前值加 1,字面解释都一样。

查一下jdk api,

public final int getAndIncrement() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return current;
    }
}
 
public final int incrementAndGet() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return next;
    }
}

由此可以看出,两个方法处理的方式都是一样的,区别在于:

getAndIncrement方法是返回旧值(即加1前的原始值)

incrementAndGet返回的是新值(即加1后的值)

  • 作为小菜鸟难免很多地方理解不到位,文中若有错误请直(bu)接(yao)指(ma)出(wo)

谢谢!

### 作用与使用方法 #### 概念与作用 原子操作如 `AtomicInteger` 是 Java 并发编程中用于保证共享变量操作原子性的工具。在多线程环境下,普通的变量操作(如自增、赋值)可能不是线程安全的,导致数据竞争问题。`AtomicInteger` 通过硬件级别的原子操作指令(如 CAS,Compare-And-Swap)来确保操作的原子性,从而避免了使用锁的性能开销。这使得它在高并发场景中具有更高的效率和更好的可扩展性[^2]。 #### 使用方法 `AtomicInteger` 提供了多种方法用于操作整型变量,这些方法包括但不限于: - `int get()`:获取当前值。 - `void set(int newValue)`:设置新值。 - `boolean compareAndSet(int expect, int update)`:比较并交换值,只有当前值等于 `expect` 时才更新为 `update`。 - `int getAndIncrement()`:获取当前值后自增。 - `int incrementAndGet()`:自增后获取新值。 - `int addAndGet(int delta)`:加上指定增量后获取新值。 以下是一个简单的示例,展示了 `AtomicInteger` 在并发环境中的使用: ```java import java.util.concurrent.atomic.AtomicInteger; public class Producer implements Runnable { private static AtomicInteger count = new AtomicInteger(); public void run() { String data = null; count.incrementAndGet(); data = "data:" + count.incrementAndGet(); System.out.println("将数据:" + data + "放入队列..."); } } ``` 在这个例子中,多个线程通过调用 `count.incrementAndGet()` 方法来确保对共享变量 `count` 的操作是线程安全的。这种方法避免了使用锁机制,同时保证了操作的原子性[^5]。 #### 底层实现原理 `AtomicInteger` 的实现依赖于 `Unsafe` ,它提供了底层的硬件级原子操作。`Unsafe` 通过 CAS 操作(Compare-And-Swap)来实现变量的原子更新。例如,`AtomicInteger` 中的 `incrementAndGet()` 方法实际上调用了 `Unsafe` 的 CAS 操作来确保自增过程的原子性。以下是一个简化的 `AtomicInteger` 定义: ```java private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; private volatile int value; public AtomicInteger(int initialValue) { value = initialValue; } public AtomicInteger() { } ``` 其中,`valueOffset` 是变量 `value` 在对象内存中的偏移地址,`Unsafe` 利用这个偏移地址来直接操作内存中的变量值,从而实现原子操作[^1]。 #### 函数式编程支持 `AtomicInteger` 还支持以函数式编程的方式更新值。例如,`accumulateAndGet` 方法允许传入一个二元操作函数,用于更新当前值。以下是一个示例: ```java import java.util.concurrent.atomic.AtomicInteger; public class Main { public static void main(String[] args) { AtomicInteger atomicInt = new AtomicInteger(5); atomicInt.accumulateAndGet(3, (x, y) -> x * y); // 5 * 3 = 15 System.out.println(atomicInt.get()); // 输出 15 } } ``` 在这个示例中,`accumulateAndGet` 方法通过传入的函数 `(x, y) -> x * y` 更新当前值,这种设计使得 `AtomicInteger` 在某些场景下更加灵活[^4]。 --- ### 相关问题 1. `AtomicInteger` 在高并发环境下如何避免锁的性能开销? 2. 如何利用 `AtomicInteger` 实现线程安全的计数器? 3. `AtomicInteger` 的 `compareAndSet` 方法如何保证操作的原子性? 4. `AtomicInteger` 与 `volatile` 变量在并发编程中的区别是什么? 5. 在哪些场景下更适合使用 `AtomicInteger` 而不是传统的锁机制?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值