Java并发学习笔记(九)-原子类AtomicInteger

AtomicInteger能够保证对一个整型的操作是原子性。像i++这个操作不是原子操作,存在竞态条件,所以需要加锁,但是加锁的性能不高,如果仅仅为了对一个整数加1。我们来看下他的实现。

    private volatile int value;

AtomicInteger本身持有一个整型变量,所有的操作都是基于这个变量的。变量由violate修饰,这个变量是保证可见性的,具体可见另一篇博客

Java并发学习笔记(六)-互斥性和内存可见性

来看一下对value加1的操作

    public final int getAndIncrement() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return current;
        }
    }

代码嵌套在一个for循环里,关键是在compareAndSet方法里。这个方法会托管给unsafe的compareAndSwapInt方法,这个步骤是靠硬件支持的,是原子操作。这个方法的意思是,如果value等于current,那么将value置为next,返回true,否则返回false,继续下一轮循环。为什么会出现值不一致,原因就在竞态条件,当本线程将value值赋给current后,其它线程可能修改了value的值,这样就会出现current和value不一致的情况。可以看出来compareAndSet类似乐观锁,及时失败。总结来说就是,value的可见性由voilate保证,原子性操作由compareAndSet来保证。

其它的方法,操作也类似,都是依靠compareAndSet来保证

时间: 2024-12-19 18:51:32

Java并发学习笔记(九)-原子类AtomicInteger的相关文章

Java并发学习之九——使用本地线程变量

本文是学习网络上的文章时的总结,感谢大家无私的分享. 1.如果创建一个类对象,实现Runnable接口,然后多个Thread对象使用同样的Runnable对象,全部的线程都共享同样的属性.这意味着,如果你在一个线程里改变一个属性,全部的线程都会受到这个改变的影响.如果希望程序里的哥哥线程的属性不会被共享,Java并发API提供了一个很清楚的机制叫本地线程变量. 2.Java并发API包括Inheritable ThreadLocal类提供线程创建线程的值的遗传性.如果线程A有一个本地线程变量,然

java jvm学习笔记九(策略文件)

欢迎装载请说明出处:http://blog.csdn.net/yfqnihao/article/details/8271407 课程源码:http://download.csdn.net/detail/yfqnihao/4866503 什么是java的策略,什么又是策略文件. 今天我换一下笔记的方式,不是直接讲概念,而是先来做一个小例子,相信你做完这个例子之后再看我对例子的讲解,你对策略,策略文件,会豁然开朗的感觉. 例子很简单,简单的才是大家的,下面跟着我(你完全可以copy我的代码). 第一

Java基础学习笔记九 Java基础语法之this和super

构造方法 我们对封装已经有了基本的了解,接下来我们来看一个新的问题,依然以Person为例,由于Person中的属性都被private了,外界无法直接访问属性,必须对外提供相应的set和get方法.当创建Person对象的时候,Person对象一创建就要明确其姓名和年龄,那该怎么做呢? 构造方法介绍 在开发中经常需要在创建对象的同时明确对象的属性值,比如员工入职公司就要明确他的姓名.年龄等属性信息.也就是在创建对象的时候就要做的事情,当使用new关键字创建对象时,怎么给对象的属性初始化值呢?这就

Java并发学习笔记一

1.并发可以提高程序运行速度,能够更好的管理程序设计. 2.在多处理器主机上,可以在这些处理器上运行多个任务,提高吞吐量:然而在单个处理器的主机上,使用并发的话,貌似要比同步的执行的程序资源开销大,因为其中增加了所谓上下文切换的代价,要从一个任务切换到另一个任务,到这里,我们可能认为在但处理器的主机上,使用并发并不能提高程序的性能,反而会消耗更多资源,然而有个问题使得并发在单个处理器上变的不同,这个问题就是阻塞.我们来看看阻塞的含义,如果程序中的某个任务因为控制范围之外的某个条件(一般是IO问题

Java并发学习笔记(八)-LinkedBlockingQueue

LinkedBlockingQueue是由链表组成的阻塞队列,先来看demo public class LinkedBlockingQueueDemo { public static void main(String[] args) { ExecutorService es = Executors.newCachedThreadPool(); BlockingQueue<Bread> queue = new LinkedBlockingQueue<Bread>(10); for(i

Java线程学习笔记(一)

一.线程的创建方式: 老掉牙的话题了,继承 java.lang.Thread父类或者实现Runnalbe接口,这里就提一句: class Thread implements Runnable Thread也是继承了Runnable接口的,Runnable才是大哥. 重写run(),run()里放的都是具体的业务,包括对线程的具体操作. class Thread1 implements Runnable { int i; Thread1(int i) { this.i = i; } @Overri

Java并发学习之五——线程的睡眠和恢复

本文是学习网络上的文章时的总结,感谢大家无私的分享. 1.Thread类的sleep方法,可以使线程睡眠.此方法接收一个整数作为参数,表示线程暂停运行的毫秒数.在调用sleep方法后,当时间结束时,JVM会安排他们CPU时间,线程会继续按指令执行. 另一种可能是使用一个有TimeUnit列举元素的sleep方法,使用线程类的sleep方法让当前线程睡眠,但是它接收的参数单位后会转成毫秒的. 2.当你调用sleep()方法,Thread离开CPU并在一段时间内停止运行.在这段时间内,他是不消耗CP

《深入Java虚拟机学习笔记》- 第7章 类型的生命周期

一.类型生命周期的开始 如图所示 初始化时机 所有Java虚拟机实现必须在每个类或接口首次主动使用时初始化: 以下几种情形符合主动使用的要求: 当创建某个类的新实例时(或者通过在字节码中执行new指令,或者通过不明确的创建.反射.克隆和反序列化): 当调用某个类的静态方法时(即在字节码中执行invokestatic指令): 当使用某个类或接口的静态字段,或者对该字段赋值时(用final修饰的静态字段除外,它被初始化为一个编译时常量表达式): 当调用Java API中的某些反射方法: 当初始化某个

[原创]java WEB学习笔记95:Hibernate 目录

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------