Java 原子操作

发布于 2022-12-23 13:55:31 字数 4321 浏览 121 评论 0

原子操作 - 计数器、域更新器

java.util.concurrent.atomic 包,可以在多线程环境下,无锁无阻塞的进行原子操作。原子类分为4种类型:计数器、域更新器、数组及复合变量。

计数器

  • AtomicBoolean:原子更新布尔值
  • AtomicInteger:原子更新整形值
  • AtomicLong:原子更新 Long 值
  • AtomicReference:原子更新引用值

AtomicInteger 常用方法

关键方法说明
int addAndGet(int delta)以原子方式将输入的数值与实例中的值(AtomicInteger里的value)相加,并返回结果
boolean compareAndSet(int expect, int update)如果输入的数值等于预期值,则以原子方式将
int getAndIncrement()以原子方式将当前值加1,注意:这里返回的是自增前的值,相当于i++。

域更新器

  • AtomicIntegerFieldUpdater:原子操作对象的整型的字段
  • AtomicLongFieldUpdater:原子操作对象的 Long 类型的字段
  • AtomicReferenceFieldUpdater:原子操作对象的引用字段

AtomicIntegerFieldUpdater 常用方法

关键方法说明
static AtomicIntegerFieldUpdater newUpdater(Class<U> tclass, String fieldName)创建一个 AtomicIntegerFieldUpdater
public int getAndIncrement(T obj)更新指定对象的整型字段,将其值加一

原子操作 - 代码示例

int 累加

static volatile int j=0;
static Runnable run = new Runnable() {
 public void run() {
 for(int i=0;i<10000;i++)
 j++;
 }
};
public static void main(String[] arg) throws Exception
{
 for(int i=0;i<50;i++)
 new Thread(run).start();
 Thread.sleep(1000);
 System.out.println("j="+j);
}
AtomicInteger累加
static volatile AtomicInteger j=new AtomicInteger(0);
static Runnable run = new Runnable() {
 public void run() {
 for(int i=0;i<10000;i++)
 j.incrementAndGet();
 }
};
public static void main(String[] arg) throws Exception
{
 for(int i=0;i<50;i++)
 new Thread(run).start();
 Thread.sleep(1000);
 System.out.println("j="+j.get());
}

AtomicIntegerFieldUpdater
public class filedUpdater{
/*
1.必须用volatile修饰
2.不能是static变量
3.private protected 都可以通过原子域更新
*/
 public volatile int i;
 public static void main(String[] arg)
 {
 filedUpdaterf = new filedUpdater();
 f.i=99;
 AtomicIntegerFieldUpdater integerUpdate = AtomicIntegerFieldUpdater.newUpdater(filedUpdater.class,"i");
 System.out.println(integerUpdate.getAndIncrement(f));
 System.out.println(f.i);
 }
}

原子操作 - 数组、复合变量

数组

  • AtomicIntegerArray:支持原子操作的Integer数组
  • AtomicLongArray:支持原子操作的Long数组
  • AtomicReferenceArray :支持原子操作的Reference数组

AtomicIntegerArray 常用方法

关键方法说明
int addAndGet(int i, int delta)指定数组下标i对应的元素增加 delta,并返回最新值。
boolean compareAndSet(inti, int expect, int update)对数组下标 i 的元素进行 CAS 操作,若下标i的值为 expect 则将值设置为 update。
int incrementAndGet(int i)对数组下标 i 进行加1操作,加完之后返回最新值。

复合变量

  • AtomicStampedReference:引用类型和整型标识的复合变量,只有引用和整型完全相等才认为操作行为是合法的。
  • AtomicMarkableReference:引用类型和布尔值标识的复合变量,只有引用和布尔值完全相等才认为操作行为是合法的。

AtomicStampedReference 常用方法

关键方法说明
AtomicStampedReference(V initialRef, int initialStamp)构造函数,传入一个对象引用和整型标记。
boolean compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp)CAS 操作,只有期望的引用和期望的整型标记完全一致时,才能操作成功。
int getStamp()返回整型标记。
V getReference()返回对象引用。

数组操作

public static void main(String[] arg) throws Exception
{
 AtomicIntegerArraya = new AtomicIntegerArray(new int[]{1,2,3});
 System.out.println("a[0]="+a.addAndGet(0,9));
 System.out.println(a);
 a.compareAndSet(0,10,11);
 System.out.println(a);
}

AtomicStampedReference 解决 ABA 问题

public static void main(String[] arg) throws Exception
{
 String str="A"; int stamp;
 AtomicStampedReference stapRef = new AtomicStampedReference(str,0);
 stapRef.compareAndSet("A","B",stapRef.getStamp(),stapRef.getStamp() + 1);
 stapRef.compareAndSet("B","A",stapRef.getStamp(),stapRef.getStamp() + 1);
 System.out.println(stapRef.getReference()+" "+stapRef.getStamp());
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

文章
评论
27 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文