`
uule
  • 浏览: 6306418 次
  • 性别: Icon_minigender_1
  • 来自: 一片神奇的土地
社区版块
存档分类
最新评论

线程安全并且无阻塞的Atomic类

 
阅读更多

原子操作AtomicInteger

 

public class AtomicLong extends Number  
                implements Serializable

 

 

J2SE 5.0提供了一组atomic class来帮助我们简化同步处理

基本工作原理是使用了同步synchronized的方法实现了对一个long, integer, 对象的增、减、赋值(更新)操作. 比如对于++运算符, AtomicInteger可以将它持有的integer 能够atomic 地递增。在需要访问两个或两个以上 atomic变量的程序代码(或者是对单一的atomic变量执行两个或两个以上的操作)通常都需要被synchronize以便两者的操作能够被当作是一个atomic的单元。 

 

简单的说,这些类都是线程安全的,支持无阻塞无锁定的 

 

Java代码 
  1. addAndGet(long delta)   
  2.     //以原子方式将给定值添加到当前值。  
  3.   
  4. getAndSet() :   
  5.     //设置新值,返回旧值.   
  6.   
  7. compareAndSet(expectedValue, newValue) :   
  8.     //如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值  
  9.     //如果更新成功,返回true, 否则返回false  
  10.     //换句话可以这样说: 将原子变量设置为新的值, 但是如果从我上次看到的这个变量之后到现在被其他线程修改了(和我期望看到的值不符), 那么更新失败   
  11.     /*  单线程下, compareAndSet返回永远为true,       
  12.      *  多线程下, 在与result进行compare时, counter可能被其他线程set了新值, 这时需要重新再取一遍再比较,       
  13.      *  如果还是没有拿到最新的值, 则一直循环下去, 直到拿到最新的那个值  
  14.     */  

 

为了提高性能,AtomicLong等类在实现同步时,没有用synchronized关键字,而是直接使用了最低层(本地c语言实现代码)来完成的,

因而你是看不到用synchronized关键字的.

比如:AtomicLong类中原子操作方法:

public final boolean compareAndSet(long expect, long update) ;

就是直接使用SUN公司低层本地代码的原子方法(native方法):

public final native boolean compareAndSwapLong(...)来实现的.

 

 

 

set()  
get()  
getAndSet()  
getAndIncrement()  
getAndDecrement()  
getAndAdd()

 

 

测试代码:

 

import java.util.concurrent.CountDownLatch;  
import java.util.concurrent.atomic.AtomicLong;  
  
import org.junit.Test;  

public class AtomicTest {  
  
    @Test  
    public void testAtomic()  
    {  
        final int loopcount = 10000;  
        int threadcount = 10;  
  
        final NonSafeSeq seq1 = new NonSafeSeq();  
        final SafeSeq seq2 = new SafeSeq();  
  
        final CountDownLatch l = new CountDownLatch(threadcount);  
  
        for(int i = 0; i < threadcount; ++i)  
        {  
            final int index = i;  
            new Thread(new Runnable() {  
  
                @Override  
                public void run() {  
                    for(int j = 0; j < loopcount; ++j)  
                    {  
  
                        seq1.inc();  
                        seq2.inc();  
                    }  
  
                    System.out.println("finished : " + index);  
                    l.countDown();  
  
                }  
            }).start();  
        }  
  
        try {  
            l.await();  
        } catch (InterruptedException e) {  
  
            e.printStackTrace();  
        }  
  
        System.out.println("both have finished....");  
  
        System.out.println("NonSafeSeq:" + seq1.get());  
        System.out.println("SafeSeq with atomic: " + seq2.get());  
  
    }  
}  
  
class NonSafeSeq{  
    private long count = 0;  
    public void inc()  
    {  
        count++;  
    }  
  
    public long  get()  
    {  
        return count;  
    }  
}  
  
class SafeSeq{  
    private AtomicLong count  = new AtomicLong(0);  
  
    public void inc()  
    {  
        count.incrementAndGet();  
    }  
  
    public long get()  
    {  
        return count.longValue();  
    }  
} 

 

 

其中NonSafeSeq是作为对比的类,直接放一个private long count不是线程安全的,而SafeSeq里面放了一个AtomicLong,是线程安全的;可以直接调用incrementAndGet来增加 

 

运行代码,可以得到类似这样的结果 

finished : 1 

finished : 0 

finished : 3 

finished : 2 

finished : 5 

finished : 4 

finished : 6 

finished : 8 

finished : 9 

finished : 7 

both have finished.... 

NonSafeSeq:91723 

SafeSeq with atomic: 100000 

 

可以看到,10个线程,每个线程运行了10,000次,理论上应该有100,000次增加,使用了普通的long是非线程安全的,而使用了AtomicLong是线程安全的; 

 

注意,这个例子也说明,虽然long本身的单个设置是原子的,要么成功要么不成功,但是诸如count++这样的操作就不是线程安全的;因为这包括了读取和写入两步操作

 

 

 

 

分享到:
评论

相关推荐

    java面试题_多线程(68题).pdf

    1. 什么是线程?...在Java Concurrency API中有哪些原⼦类(atomic classes)? 8. 什么是Executors框架? 9. 什么是阻塞队列?如何使⽤阻塞队列来实现⽣产者-消费者模型? 10. 什么是Callable和Future?

    atomic_queue:C ++无锁队列

    为了获得尽可能低的延迟,人们无法承受OS内核中的阻塞,因为阻塞线程的唤醒延迟约为1-3微秒,而此队列的往返时间可以低至150纳秒。 超低延迟应用程序仅需此而已。 极简主义带来了回报,请参阅。 可用的容器有: ...

    Java-并发(Concurrent)编程

    多线程核心知识(概念、线程状态、线程安全问题、三大特性) 同步代码块Synchronized及其实现原理 volatile关键字及其实现原理 多线程在JVM中的实现原理 JUC概述 原子类Atomic-CAS及其实现原理 锁Lock-AQS核心原理...

    基础技术部牛路《Java多线程入阶分享》纯干货

    3.阻塞队列:put和take、offer和poll、drainTo 4.线程间通信:lock、condition、wait、notify、notifyAll 5.Lock-free:atomic、concurrentMap.putIfAbsent、CopyOnWriteArrayList 6.关于锁的经验介绍 7.并发流程...

    synchronized ReentrantLock volatile Atomic 原理分析.docx

    原理 synchronized关键字是通过字节码指令来实现的 synchronized关键字编译后会在同步块...如果获取失败,那么当前线程阻塞,直到锁被对另一个线程释放 执行monitorexit指令时,计数器减一,当为0的时候锁释放

    2万字Java并发编程面试题合集(含答案,建议收藏)

    在 Java Concurrency API 中有哪些原子类(atomic classes)?11、Java Concurrency API 中的 Lock 接口(Lock interface)是什么?对比同步它有什么优势?12、什么是 Executors 框架?13、什么是阻塞队列?阻塞队列的...

    javaSE代码实例

    17.7 线程安全的单变量操作 403 17.7.1 atomic包简介 403 17.7.2 atomic包中类的具体使用 404 17.8 障碍器 406 17.8.1 CyclicBarrier类简介 406 17.8.2 CyclicBarrier类的具体使用 407 ...

    JAVA_API1.6文档(中文)

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...

    并发编程笔记20190526.docx

    第二章 线程的并发工具类 21 一、 Fork/Join框架的介绍 21 1、实现步骤: 22 2、工作窃取算法 22 3、分而治之 23 4、Fork/Join使用的标准范式 24 5、Fork/Join框架的异常处理 26 6、Fork/Join框架的实现原理 26 二、...

    java jdk-api-1.6 中文 chmd

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...

    java api最新7.0

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 JAR ...

    Java并发程序设计教程

    3、阻塞队列: put和take、offer和poll、drainTo 4、线程间的协调手段:lock、condition、wait、notify、notifyAll☆☆☆ 5、Lock-free: atomic、concurrentMap.putIfAbsent、CopyOnWriteArrayList☆☆☆ 6、关于锁...

    event-listener:通知异步任务或线程

    例子等到另一个线程设置一个布尔标志: use std :: sync :: atomic :: {AtomicBool, Ordering};use std :: sync :: Arc;use std :: thread;use std :: time :: Duration;use event_listener :: Event;let flag = Arc...

    JavaAPI1.6中文chm文档 part1

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...

    JDK_1_6 API

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 JAR...

    JavaAPI中文chm文档 part2

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...

    [Java参考文档]

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...

    [Java参考文档].JDK_API 1.6

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 JAR ...

    Java 1.6 API 中文 New

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 JAR ...

Global site tag (gtag.js) - Google Analytics