Java多线程和并发面试题(附答案)第6题

Java多线程和并发面试题(附答案)第6题

java 多线程admin2020-06-30 16:23:5911A+A-

  AtomicBoolean是java.util.concurrent.atomic包下的原子变量,这个包里面提供了一组原子类。其基本的特性就是在多线程环境下,当有多个线程同时执行这些类的实例包含的方法时,具有排它性,即当某个线程进入方法,执行其中的指令时,不会被其他线程打断,而别的线程就像自旋锁一样,一直等到该方法执行完成,才由JVM从等待队列中选择一个另一个线程进入,这只是一种逻辑上的理解。实际上是借助硬件的相关指令来实现的,不会阻塞线程(或者说只是在硬件级别上阻塞了)。

  AtomicBoolean,在这个Boolean值的变化的时候不允许在之间插入,保持操作的原子性。下面将解释重点方法并举例:

  比较AtomicBoolean和expect的值,如果一致,执行方法内的语句。其实就是一个if语句。

  把AtomicBoolean的值设成update,比较最要的是这两件事是一气呵成的,这连个动作之间不会被打断,任何内部或者外部的语句都不可能在两个动作之间运行。为多线程的控制提供了解决的方案。

  首先我们看下在不使用 AtomicBoolean 情况下,代码的运行情况:

  从上面的运行结果我们可看到,两个线程运行时,都对静态变量exists同时做操作,并没有保证exists静态变量的原子性,也就是一个线程在对静态变量exists进行操作到时候,其他线程必须等待或不作为。等待一个线程操作完后,才能对其进行操作。

  可以从上面的运行结果看出仅仅一个线程进行工作,因为exists.compareAndSet(false,true)提供了原子性操作,比较和赋值操作组成了一个原子操作,中间不会提供可乘之机。使得一个线程操作,其他线程等待或不作为。

  以上示例新建了一个默认值为false的AtomicBoolean。如果你想要为AtomicBoolean实例设置一个显式的初始值,那么你可以将初始值传给AtomicBoolean的构造子:

  你可以通过使用get()方法来获取一个AtomicBoolean的值。示例如下:

  你可以通过使用set()方法来设置一个AtomicBoolean的值。示例如下:

  compareAndSet()方法允许你对AtomicBoolean的当前值与一个期望值进行比较,如果当前值等于期望值的话,将会对AtomicBoolean设定一个新值。compareAndSet()方法是原子性的,因此在同一时间之内有单个线程执行它。因此compareAndSet()方法可被用于一些类似于锁的同步的简单实现。以下是一个compareAndSet()示例:

  AtomicInteger,一个提供原子操作的Integer的类。在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。

  从上面的例子中我们可以看出:使用AtomicInteger是非常安全的,而且因为AtomicInteger由硬件提供原子操作指令实现的,在非激烈竞争的情况下,开销更小,速度更快。AtomicInteger是使用非阻塞算法来实现并发控制的。AtomicInteger的关键域只有以下3个:

  这里,unsafe是java提供的获得对对象内存地址访问的类,注释已经清楚的写出了,它的作用就是在更新操作时提供“比较并替换”的作用。实际上就是AtomicInteger中的一个工具。valueOffset是用来记录value本身在内存的偏移地址的,这个记录也主要是为了在更新操作在内存中找到value的位置,方便比较。

  注意:value是用来存储整数的时间变量,这里被声明为volatile,就是为了保证在更新操作时,当前线程可以拿到value最新的值(并发环境下,value可能已经被其他线程更新了)。

  优点:最大的好处就是可以避免多线程的优先级倒置和死锁情况的发生,提升在高并发处理下的性能。

  本示例将创建一个初始值为0的AtomicInteger。如果你想要创建一个给

  你可以使用get()方法获取AtomicInteger实例的值。示例如下:

  以上示例创建了一个初始值为123的AtomicInteger,而在第二行将其值更新为234。

  AtomicInteger类包含有一些方法,通过它们你可以增加AtomicInteger的值,并获取其值。这些方法如下:

  第一个addAndGet()方法给AtomicInteger增加了一个值,然后返回增加后的值。getAndAdd()方法为AtomicInteger增加了一个值,但返回的是增加以前的AtomicInteger的值。具体使用哪一个取决于你的应用场景。以下是这两种方法的示例:

  java.util.concurrent.atomic.AtomicIntegerArray类提供了可以以原子方式读取和写入的底层int数组的操作,还包含高级原子操作。AtomicIntegerArray支持对底层int数组变量的原子操作。它具有获取和设置方法,如在变量上的读取和写入。也就是说,一个集合与同一变量上的任何后续get相关联。原子compareAndSet方法也具有这些内存一致性功能。

  AtomicIntegerArray本质上是对int[]类型的封装。使用Unsafe类通过CAS的方式控制int[]在多线程下的安全性。它提供了以下几个核心API:

  上述代码第2行,申明了一个内含10个元素的数组。第3行定义的线个元素进行累加操作,每个元素各加1000次。第11行,开启10个这样的线程。因此,可以预测,如果线。反之,如果线程不安全,则部分或者全部数值会小于10000。

  AtomicLong、AtomicLongArray的API跟AtomicInteger、AtomicIntegerArray在使用方法都是差不多的。区别在于用前者是使用原子方式更新的long值和long数组,后者是使用原子方式更新的Integer值和Integer数组。两者的相同处在于它们此类确实扩展了Number,允许那些处理基于数字类的工具和实用工具进行统一访问。在实际开发中,它们分别用于不同的场景。这个就具体情况具体分析了,下面将举例说明AtomicLong的使用场景(使用AtomicLong生成自增长ID)。

  从运行结果我们看到,不管是哪个线程。它们获得的ID是不会重复的,保证的ID生成的原子性,避免了线程安全上的问题。

点击这里复制本文地址 免责声明:本站内容由程序自动采集于互联网,无人工干预,只作交流和学习使用,本站不储存任何资源内容,如有侵权请联系qq邮箱798244092@qq.com立刻删除,谢谢!

支持Ctrl+Enter提交

java教程 © All Rights Reserved.  
Powered by 多多资源网 Themes by 多多资源网
联系我们| 关于我们| 留言建议| 网站管理