AtomicBoolean介绍

AtomicBoolean概念、使用案例

它提供了线程安全的方式来操作布尔值,它可以确保多个线程对同一个布尔值的操作是原子的,并且只能由一个线程执行对这个布尔值的操作避免了繁琐的同步措施,它提供了高效的非阻塞算法实现,可以大大提成程序的并发性能,AtomicBoolean的API设计非常简单易用。使用案例如下:
BarWorker实现了Runnable接口,该类中有个boolean属性,需求是:有多个BarWorker线程的情况下,只有一个线程执行boolean属性=true的逻辑。下面分别用Boolean、和AtomicBoolean编码,验证只有AtomicBoolean才能实现需求。

首先通过Boolean:

import java.util.concurrent.TimeUnit;

public class BarWorker implements Runnable {

    private static boolean exists = false;

    private String name;

    public BarWorker(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        if (!exists) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e1) {
                // do nothing
            }
            exists = true;
            System.out.println(name + " enter");
            System.out.println(name + " working");
            System.out.println(name + " leave");
        } else {
            System.out.println(name + " give up");
        }
    }
    
    public static void main(String[] args) {

        BarWorker bar1 = new BarWorker("bar1");
        BarWorker bar2 = new BarWorker("bar2");
        new Thread(bar1).start();
        new Thread(bar2).start();
    }
}

执行结果:发现并不能实现需求

bar1 enter  
bar2 enter  
bar1 working  
bar2 working  
bar1 leave  
bar2 leave  

通过AtomicBoolean编码如下:

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

public class BarWorker2 implements Runnable {

    private static AtomicBoolean exists = new AtomicBoolean(false);

    private String name;

    public BarWorker2(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        if (exists.compareAndSet(false, true)) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e1) {
                // do nothing
            }
            System.out.println(name + " enter");
            System.out.println(name + " working");
            System.out.println(name + " leave");
        } else {
            System.out.println(name + " give up");
        }
    }

    public static void main(String[] args) {
        BarWorker2 bar1 = new BarWorker2("bar1");
        new Thread(bar1).start();
        BarWorker2 bar2 = new BarWorker2("bar2");
        new Thread(bar2).start();
    }
}em.out.println(name + " give up");
        }
    }

    public static void main(String[] args) {
        BarWorker2 bar1 = new BarWorker2("bar1");
        new Thread(bar1).start();
        BarWorker2 bar2 = new BarWorker2("bar2");
        new Thread(bar2).start();
    }
}

执行结果如下:实现了需求,可见AtomicBoolean的compareAndSet方法:在比较、更改2个操作之间,不能执行其他指令

bar1 enter
bar2 give up
bar1 working
bar1 leave

AtomicBoolean核心api及原理

AtomicBoolean类是Java的java.util.concurrent.atomic包中的一个原子类,用于对布尔值进行原子操作,以下是AtomicBoolean类中主要方法的含义:

  1. AtomicBoolean(boolean initialValue)
    构造函数,用于创建一个具有给定初始值的AtomicBoolean实例。

  2. boolean get()
    获取当前值,此方法以原子方式读取AtomicBoolean实例的当前值,并返回它。

  3. void set(boolean newValue)

  • 设置新值,此方法以原子方式设置AtomicBoolean实例的值。
  • set(boolean newValue) 方法,使用 Unsafe 类的 putOrderedObject() 方法来设置新的布尔值,虽然这个方法名看起来可能不是原子的,但实际上对于布尔值这种单个字段的写入,它是原子的,不过,set() 操作本身并不保证其他线程的立即可见性,但在后续的读取操作中,由于 volatile 关键字的存在,会保证读取到的是最新的值
  1. boolean compareAndSet(boolean expect, boolean update)
  • 如果当前值与预期值expect相等,则以原子方式将该值设置为update,并返回true;否则返回false,这是一个条件原子更新操作常用于实现无锁算法或数据结构。
  • Unsafe类提供了一些可以直接操作内存的低级方法,包括原子性的比较和交换(compare-and-swap,CAS)操作,CAS是一种无锁算法,它包含三个操作数——内存位置(V)、预期原值(A)和新值(B),CAS会检查内存位置V的值是否与预期原值A相等,如果是,则将该位置的值设置为新值B,这个过程是原子的,也就是说,在这个操作进行期间,不会有其他线程能够改变内存位置V的值
  • AtomicBoolean的内部实现中,布尔值被存储在一个volatile修饰的字段中以确保所有线程都能看到最新的值volatile关键字保证了内存可见性和禁止指令重排序
  1. boolean getAndSet(boolean newValue)
  • 以原子方式设置AtomicBoolean的值为newValue,并返回旧值,这个方法可以用于实现一些需要知道旧值的同时更新为新值的场景,也能保证原子性
  • 这个方法会设置新的值,并返回旧的值,它内部也是通过 CAS 操作来实现的。
  1. boolean weakCompareAndSet(boolean expect, boolean update)
    与compareAndSet方法类似,但允许更大的并发性,可能会失败更多(即返回false),即使在当前值与预期值相同的情况下也是如此,这个方法通常用于循环中,直到成功为止。不过,由于它可能“失败更多”,因此它通常比compareAndSet更快。

  2. String toString()
    返回AtomicBoolean实例的当前值的字符串表示形式(“true"或"false”)。

  3. int hashCode()
    返回该AtomicBoolean实例的哈希码值。

  4. boolean equals(Object obj)
    检查此AtomicBoolean实例与另一个对象是否相等。如果对象也是一个AtomicBoolean实例,并且两个实例的当前值相同,则返回true;否则返回false。

总结

AtomicBoolean类的优点在于原子性操作,可确保在多线程环境中对布尔值的读取和设置不会产生竞态条件,同时,它的性能通常优于使用synchronized的代码,因为它避免了线程阻塞和上下文切换的开销。同时,AtomicBoolean还提供了丰富的API,如compareAndSet和getAndSet等。但是,虽然AtomicBoolean提供了原子性保证,但它却无法解决并发中的可见性和有序性问题,这里需要特别注意。

其他

volatile 链接
CountDownLatch:链接1链接2

Thread.join 链接

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值