java-多线程深入(五)Atomic分析

(一)Atomic的使用

java.util.concurrent中提供了atomic原子包,可以实现原子操作(atomic operation),即在多线程环境中,执行的操作不会被其他线程打断。

/**
 * atomic简单demo
 * 
 * @author peter_wang
 * @create-time 2014-6-9 上午9:29:58
 */
public class AtomicDemo
    extends Thread {

    private static final AtomicInteger TEST_INT = new AtomicInteger();

    @Override
    public void run() {
        TEST_INT.incrementAndGet();
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        for (int i = 0; i < 1000; i++) {
            AtomicDemo demo = new AtomicDemo();
            demo.start();
            try {
                demo.join();
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        System.out.println("最终结果:"+TEST_INT);
    }

}

运行结果:

最终结果:1000

多个线程对AtomicInteger类型的变量进行自增操作,运算结果无误。若用普通的int变量,i++多线程操作可能导致结果有误。

(二)原理分析

源码分析:

incrementAndGet函数

/**
     * Atomically increments by one the current value.
     *
     * @return the updated value
     */
    public final int incrementAndGet() {
        for (;;) {
            //获取当前值value
            int current = get();
            int next = current + 1;
            //循环执行到递增成功
            if (compareAndSet(current, next))
                return next;
        }
    }
private volatile int value;

value是volatile类型,确保此线程能获取到最新值。

方法不断获取value值再进行递增操作,直至操作成功。

public final boolean compareAndSet(int expect, int update) {
	return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

compareAndSet使用Unsafe调用native本地方法CAS(CompareAndSet)递增数值。

(三)CAS简要

CAS利用CPU调用底层指令实现。

单一处理器,进行简单的读写操作时,能保证自身读取的原子性,多处理器或复杂的内存操作时,CAS采用总线加锁或缓存加锁方式保证原子性。

1.总线加锁

如i=0初始化,多处理器多线程环境下进行i++操作下,处理器A和B同时读取i值到各自缓存,分别进行递增,回写值i=1相同。处理器提供LOCK#信号,进行总线加锁后,处理器A读取i值并递增,处理器B被阻塞不能读取i值。

2.缓存加锁

总线加锁,在LOCK#信号下,其他线程无法操作内存,性能较差,缓存加锁能较好处理该问题。

缓存加锁,处理器A和B同时读取i值到缓存,处理器A提前完成递增,数据立即回写到主内存,并让处理器B缓存该数据失效,处理器B需重新读取i值。

时间: 2024-10-15 04:00:55

java-多线程深入(五)Atomic分析的相关文章

Java 多线程(五) 多线程的同步

Java 多线程(五) 多线程的同步 为什么要引入同步机制 在多线程环境中,可能会有两个甚至更多的线程试图同时访问一个有限的资源.必须对这种潜在资源冲突进行预防. 解决方法:在线程使用一个资源时为其加锁即可. 访问资源的第一个线程为其加上锁以后,其他线程便不能再使用那个资源,除非被解锁. 程序实例 用一个取钱的程序例子,来说明为什么需要引入同步. 在使用同步机制前,整体程序如下: public class FetchMoneyTest { public static void main(Stri

Java多线程(五)、多线程其他知识简要介绍(转)

Java多线程(五).多线程其他知识简要介绍 分类: javaSE综合知识点 2012-09-19 18:12 1413人阅读 评论(1) 收藏 举报 一.线程组 [java] view plaincopyprint? /** * A thread group represents a set of threads. In addition, a thread * group can also include other thread groups. The thread groups form

Java 多线程 volitile 和 atomic

Java 多线程 volitile 和 atomic volitile关键字 public class MTester { public static class TestKey{ int x = 0; } public static TestKey key0 = new TestKey(); public static void main(String[] args) { Thread thread = new Thread(()->{ while (key0.x == 0){ } Syste

java多线程(五)

Java 多线程同步 锁机制与synchronized 打个比方:一个object就像一个大房子,大门永远打开.房子里有很多房间(也就是方法).这些房间有上锁的(synchronized方法), 和不上锁之分(普通方法).房门口放着一把钥匙(key),这把钥匙可以打开所有上锁的房间.另外我把所有想调用该对象方法的线程比喻成想进入这房子某个 房间的人.所有的东西就这么多了,下面我们看看这些东西之间如何作用的. 在此我们先来明确一下我们的前提条件.该对象至少有一个synchronized方法,否则这

Java多线程核心技术(五)单例模式与多线程

本文只需要考虑一件事:如何使单例模式遇到多线程是安全的.正确的 1.立即加载 / "饿汉模式" 什么是立即加载?立即加载就是使用类的时候已经将对象创建完毕,常见的实现办法就是直接 new 实例化. public class MyObject { private static MyObject myObject = new MyObject(); public MyObject(){ } public static MyObject getInstance(){ return myObj

java多线程总结五:线程池的原理及实现

1.线程池简介:     多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.        假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中执行任务的时间,T3 销毁线程时间.    如果:T1 + T3 远大于 T2,则可以采用线程池,以提高服务器性能.                 一个线程池包括以下四个基本组成部分:                 1.线程池管理器(ThreadPool):用于创建并管

Java多线程系列五——列表类

参考资料: http://xxgblog.com/2016/04/02/traverse-list-thread-safe/ 一些列表类及其特性  类 线程安全 Iterator 特性 说明 Vector 是 fail-fast 内部方法用synchronized修饰,因此执行效率较低 1. 线程安全的列表类并不意味着调用它的代码就一定线程安全 2. 只有CopyOnWriteArrayList能支持在遍历时修改列表元素 ArrayList 否 fail-fast 在多线程环境中使用不当易出错

Java多线程系列一——Atomic类

参考资料:https://fangjian0423.github.io/2016/03/16/java-AtomicInteger-analysis/http://www.cnblogs.com/549294286/p/3766717.html 最近面试遇到一道编程题,要求两个线程交替打印[0,100]的数字,其中一个只打印奇数,另一个只打印偶数,并且给出特别明显的提示AtomicInteger,当时我在想简直是送分题啊,但事后回想由于手写又没有记得所有API,很多地方不完美,所以面试官最后让我

JAVA多线程(五)模式-Guarded Suspension

Guarded Suspension 多线程共享一个资源,该资源的使用是有条件的. 适用环境 共享资源的占用是有条件而非直接占用的. 样例 幼教收作业:仨熊孩子俩幼教,俩幼教面前一个长桌子,总共只能放两个作业. 熊孩子 package GuardedSuspension; public class Child implements Runnable { private Table table=null; private String myName=null; private int cnt=1;

java多线程(一)-五种线程创建方式

简单使用示例 Java 提供了三种创建线程的方法: 通过实现 Runnable 接口: 通过继承 Thread 类本身: 通过 Callable 和 Future 创建线程. 还有 定时器 线程池 下面第一个类给出了四种创建方式,第二个类是定时器示例. ① public class ThreadStartTest { public static void main(String[] args) throws ExecutionException, InterruptedException { S