Java 并发编程之原子引用类

之前讲到 volatile 关键字,只能保证变量的可见性和有序性

要想保证其原子性,则需要用到 Java 并发包下面的原子类

原子类的方法都是调用 Unsafe 的 cas 方法,cas 其实是操作系统底层的一条原语指令

但是原子类只能保证单个变量的原子性,这个时候想保证自定义对象的原子性,就需要用到原子引用类

1. AtomicReference<T>

   泛型,接收一个类作为原子类型引用

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

class Book{
    String  name;
    int price;
    public Book(String name, int price){
        this.name = name;
        this.price = price;
    }
}
public class AtomicReferenceDemo {

    static AtomicReference<Book> atomicReference = new AtomicReference<>(new Book("z3", 100));
    public static void main(String[] args) {
        new Thread(()->{
            Book z3 = atomicReference.get();
            System.out.println(Thread.currentThread().getName()+"\t"+"当前书名字 = "+z3.name+"  当前书价格 = "+z3.price);
            try{ TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e){e.printStackTrace();}
            atomicReference.compareAndSet(z3, new Book("l4",200));
        },"t1").start();

        new Thread(()->{
            Book z3 = atomicReference.get();
            System.out.println(Thread.currentThread().getName()+"\t"+"当前书名字 = "+z3.name+"  当前书价格 = "+z3.price);
            try{ TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e){e.printStackTrace();}
            boolean l4 = atomicReference.compareAndSet(z3, new Book("w5", 500));
            System.out.println(Thread.currentThread().getName()+"\t"+"修改结果:"+l4);
            System.out.println("当前书的名字="+atomicReference.get().name+"  "+"当前书的价格为:"+atomicReference.get().price);
        },"t2").start();

    }
}

2. AtomicMarkableReference 

   记录当前值是否被修改过: true / false

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicMarkableReference;

public class AtomicMarkableReferenceDemo {

    static AtomicMarkableReference markedAbleReference = new AtomicMarkableReference<>(100,false);

    public static void main(String[] args) {
        new Thread(()->{
            boolean marked = markedAbleReference.isMarked();
            System.out.println(Thread.currentThread().getName()+"\t"+"默认标识符:"+marked);
            try{TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e){e.printStackTrace();}
            markedAbleReference.compareAndSet(100,1000,marked,!marked);
        },"t1").start();

        new Thread(()->{
            boolean marked = markedAbleReference.isMarked();
            System.out.println(Thread.currentThread().getName()+"\t"+"默认标识符:"+marked);
            try{TimeUnit.SECONDS.sleep(2);}catch (InterruptedException e){e.printStackTrace();}
            boolean b = markedAbleReference.compareAndSet(100, 2000, marked, !marked);
            System.out.println(Thread.currentThread().getName()+"\t"+"操作结果:"+b);
            System.out.println(Thread.currentThread().getName()+"\t"+"markedAbleReference:"+markedAbleReference.isMarked());
            System.out.println(Thread.currentThread().getName()+"\t"+"引用值:"+markedAbleReference.getReference());

        },"t2").start();
        
    }
}

3. AtomicStampeReference 带版本戳号的原子引用类

   每个线程修改之后都更新版本号,在每一个线程使用cas方法提交更新时,都必须比较值和版本号

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;

public class AtomicStampedReferenceDemo {
    static AtomicStampedReference<String> atomicStampedReference = new AtomicStampedReference<>("hello",1);

    public static void main(String[] args) {
        new Thread(()->{
            int stampe = atomicStampedReference.getStamp();
            String reference = atomicStampedReference.getReference();
            System.out.println(Thread.currentThread().getName()+"\t"+"当前版本戳 = "+stampe+"  当前值内容为 = "+reference);
            try{ TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e){e.printStackTrace();}
            atomicStampedReference.compareAndSet("hello","t1-hello",1,2);
        },"t1").start();

        new Thread(()->{
            int stampe = atomicStampedReference.getStamp();
            String reference = atomicStampedReference.getReference();
            System.out.println(Thread.currentThread().getName()+"\t"+"当前版本戳 = "+stampe+"  当前值内容为 = "+reference);
            try{ TimeUnit.SECONDS.sleep(2);}catch (InterruptedException e){e.printStackTrace();}
            boolean b = atomicStampedReference.compareAndSet("hello", "t2-hello", 1, 2);
            System.out.println(Thread.currentThread().getName()+"\t"+"修改是否成功: "+b);
            System.out.println(Thread.currentThread().getName()+"\t"
                    +"修改后当前版本戳 = "+atomicStampedReference.getStamp()
                    +"  修改后当前值内容为 = "+atomicStampedReference.getReference());

        },"t2").start();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值