AtomicInteger操作Semphore的使用

标题:AtomicInteger的操作

学习了解到了AtomicInteger,就分享给大家了,自己的阅历有限,有需要改正的地方就请大佬前辈们指出来, 自己阅读了一些博主的AtomicInteger的操作 自己的认知如下:

高并发的情况下,count++无法保证原子性,往往会出现问题,所以引入AtomicInteger类。
图1:没有AtomicIteger的时候count++运行线程;
在这里插入图片描述运行结果是:在这里插入图片描述 图2:这是有AtomicIteger的时候操作运行线程
在这里插入图片描述结果运行结果是:在这里插入图片描述
由上示图可以理解到:SemaphoreAtomicInteger
1、Semaphore是什么?

Semaphore叫信号量,Semaphore有两个目的,第一个是多个共享资源互斥使用,第二个是并发线程数的控制;
Semaphore也是一个线程同步的辅助类,可以维护当前访问自身的线程个数,并提供了同步机制。使用Semaphore可以控制同时访问资源的线程个数

acquire():从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。
release():释放一个许可,将其返回给信号量。
线程需要通过acquire()方法获取许可,而release()释放许可。如果许可数达到最大活动数,那么调用acquire()之后,便进入等待队列,等待已获得许可的线程释放许可,从而使得多线程能够合理的运行。

1、Semaphore的作用?

1:加锁、
2:异步返回、
3:控制线程并发数这三个用途

这是一个博客的地址:Semaphore的应用
2、AtomicInteger是什么?

AtomicInteger它不能当作Integer来使用
AtomicInteger类是系统底层保护的int类型,通过提供执行方法的控制进行值的原子操作。
从JAVA 1.5开始,AtomicInteger 属于java.util.concurrent.atomic 包下的一个类。
AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减。
AtomicInteger提供原子操作来进行Integer的使用,因此十分适合高并发情况下的使用。

(1):AtomicInteger使用场景:

   作为多个线程同时使用的原子计数器。
   1:原子计数器:AtomicIntegerclass提供了一些以原子方式执行加法和减法操作的方法。
     addAndGet()- 以原子方式将给定值添加到当前值,并在添加后返回新值。
     getAndAdd() - 以原子方式将给定值添加到当前值并返回旧值。
     incrementAndGet()- 以原子方式将当前值递增1并在递增后返回新值。它相当于i ++操作。
     getAndIncrement() - 以原子方式递增当前值并返回旧值。它相当于++ i操作。
     decrementAndGet()- 原子地将当前值减1并在减量后返回新值。它等同于i-操作。
     getAndDecrement() - 以原子方式递减当前值并返回旧值。它相当于-i操作。
  2: 在比较和交换操作中实现非阻塞算法
比较和交换操作将内存位置的内容与给定值进行比较,并且只有它们相同时,才将该内存位置的内容修改为给定的新值。这是作为单个原子操作完成的。
原子性保证了新值是根据最新信息计算出来的; 如果在此期间该值已被另一个线程更新,则写入将失败。

:AtomicInteger保证了线程的安全运行;而单纯的count++会导致高并发时统计有误;
而AtomicInteger为什么能够达到多而不乱,处理高并发应付自如呢?

1;这是由硬件提供原子操作指令实现的。在非激烈竞争的情况下,开销更小,速度更快。Java.util.concurrent中实现的原子操作类包括:
AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference。等
  另外其底层就是volatile和CAS 共同作用的结果:
  
2;有的同学肯定就会问了 那count++怎么保证线程的安全运行呢?
如果用count++安全运行线程;这里就需要加锁(synchronized)
没有AtomicIteger的时候count++运行线程
public synchronized static void add() {
count++; //若要线程安全执行执行count++,需要加锁
}
我们要知道synchronized关键字可以保证可见性和有序性却无法保证原子性。而这个AtomicInteger的作用就是为了保证原子性;
原子类一览图参考如下:这是一个博主原子类图
在这里插入图片描述

 1.首先使用了volatile 保证了内存可见性。   
     volatile  修饰了的变量,
    不具备线程原子性
    具备线程可见性
    具备线程有序性
 2.使用了CAS(compare-and-swap)算法 保证了原子性。

这里是一个关于volatile的文章
面试官最爱的volatile
(AtomicInteger保护线程的安全 具有原子性,可见性)
原子性:
在Java中可以**使用synchronized来保证原子性,**被synchronized修饰的代码块及方法,在同一时间,只能被单个线程访问。
通过对代码的反编译,我们可以知道synchronized采用ACC_SYNCHRONIZED和monitorenter、monitorexit两个指令来实现同步方法和同步代码块。

可见性:
Java中的volatile关键字来保证可见性,被其修饰的变量在被修改后会立即同步到主内存,被其修饰的变量在每次使用之前都从主内存刷新获得最新值。因此,可以使用volatile来保证多线程操作时变量的可见性。
另外,synchronized和final也是可以通过不同的实现方式来实现可见性的。后面继续详解

Semaphore共享锁的使用
信号量(Semaphore),又被称为信号灯,在多线程环境下用于协调各个线程, 以保证它们能够正确、合理的使用公共资源。信号量维护了一个许可集合,我们在初始化Semaphore时需要为这个许可集合传入一个数量值,该数量值代表同一时间能访问共享资源的线程数量。线程可以通过acquire()方法获取到一个许可,然后对共享资源进行操作,注意如果许可集合已分配完了,那么线程将进入等待状态,直到其他线程释放许可才有机会再获取许可,线程释放一个许可通过release()方法完成

```javascript
 ‘总结:信号量底层AQS获取共享锁。信号量是一个共享锁,他允许一批数据进去。这是他的特性。
 信号量只能保证每次100,不保证100是否是并发问题,  共享锁就是允许多个线程同时获取一个锁,一个锁可以同时被多个线程拥有。然后进行count++ 就会有误,这时候 AtomicInteger就保证了他的原子性。
 ’

我是一个热爱编程的人,但是表述肯定差强人意 有问题可以咨询我哦
自己的经验不足,希望能慢慢的进步给来大家带来更多的易懂文章,不对的地方欢迎大佬们指出
祝大家遨游在学习的海洋里.工作顺利
谢谢大家的阅读 我会加油哒!祝您拿得高薪资

我们共勉之

这里是一个博客的 ABC 的输出方法 ,可以多了解一下
多线程 循环输出ABC AtomicInteger和Semaphore方案

发布了17 篇原创文章 · 获赞 0 · 访问量 493

猜你喜欢

转载自blog.csdn.net/sqL520lT/article/details/104986120