您的位置:首页 > 编程语言 > Java开发

java并发包-AtomicInteger的并发处理

2012-05-22 09:03 323 查看
今天我们研究一下java并发包下面的 AtomicInteger 类

java.util.concurrent.atomic 包中添加原子变量类。所有原子变量类都公开“比较并设置”原语,这些原语都是使用平台上可用的最快本机结构(比较并交换、加载链接/条件存储,最坏的情况下是旋转锁)来实现的。 java.util.concurrent.atomic 包中提供了原子变量的 9 种风格(AtomicInteger、AtomicLong、 olean、原子整型、长型、及原子标记引用和戳记引用类的数组形式,
其原子地更新一对值)。

AtomicInteger,一个提供原子操作的Integer的类。在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。
简单的来看一下 AtomicInteger 提供的接口。
public final int get()   //获取当前的值
public final int getAndSet(int newValue)  //取当前的值,并设置新的值
public final int getAndIncrement()  //获取当前的值,并自增
public final int getAndDecrement()  //获取当前的值,并自减
public final int getAndAdd(int delta)  //获取当前的值,并加上预期的值 ... ...


下面的程序是使用原子变量后的计数器:

package test;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicCounter {
private AtomicInteger value = new AtomicInteger();
public int getValue() {    return value.get();  }
public int increment() {    return value.incrementAndGet();  }
public int increment(int i) {    return value.addAndGet(i);  }
public int decrement() {    return value.decrementAndGet();  }
public int decrement(int i) {    return value.addAndGet(-i);  } }


下面写一个测试类:

package test;
public class AtomicCounterTest extends Thread {
AtomicCounter counter;
public AtomicCounterTest(AtomicCounter counter) {
this.counter = counter;
}
@Override
public void run() {
int i = counter.increment();
System. .println("generated  out number:" + i);
}
public static  void main(String[] args) {
AtomicCounter counter = new AtomicCounter();
for (int i = 0; i < 10; i++) {//10个线程
new AtomicCounterTest(counter).start();
}
}
}

generated number:1
generated number:2
generated number:3
generated number:4
generated number:5
generated number:7
generated number:6
generated number:9
generated number:10
generated number:8


会发现 10 个线程运行中,没有重复的数字,原子量类使用本机 CAS实现了值修改的原子性。

看到网上一些资料对这个类的一些问题,这里简要摘录几个关键的,尝试解答一下:
1、为什么AtomicInteger里面的compareAndSet和weakCompareAndSet方法实现完全一样,注释说明却不同?
核心观点就是人家保留更改这个实现的权利。现在一样可能是暂时的,将来可能会不一样,所以使用接口时,还是按照人家接口说明来吧。
2、他比直接使用传统的java锁机制(阻塞的)有什么好处?
最大的好处就是可以避免多线程的优先级倒置和死锁情况的发生,当然高并发下的性能提升也是很重要的。
3、使用了他,并发环境下就一定没问题了吗?
在某些场景下,可能会造成业务问题。但是多数的场景(比如高效的计数器实现)是不用担心这个问题的。
好了,暂时写到这里吧,大家有什么不明白的可以直接提问,如果文章有有什么错误大家也及时提出来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: