`
uule
  • 浏览: 6358754 次
  • 性别: 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++这样的操作就不是线程安全的;因为这包括了读取和写入两步操作

 

 

 

 

分享到:
评论

相关推荐

    线程安全测试类

    4. **非阻塞同步替代方案**:Java提供了多种非阻塞同步机制,如`java.util.concurrent`包中的`ReentrantLock`、`Semaphore`和`Atomic`类等。这些工具可以在某些情况下提供更好的性能,但使用它们需要更深入的理解和...

    java线程安全总结.doc

    3. **Atomic类**:提供原子操作,例如`AtomicInteger`,`AtomicReference`等,可以在没有同步的情况下实现线程安全。 4. **线程池**:通过预先创建并管理一定数量的线程,减少线程创建和销毁的开销,提高系统效率。 ...

    Action是否线程安全

    - **使用并发工具类**:`java.util.concurrent`包提供了很多并发工具类,如`Atomic`类、`ConcurrentHashMap`等,它们提供了原子操作,有助于实现线程安全。 - **避免阻塞操作**:在EDT中处理`ActionEvent`时,避免...

    基于C++的线程安全容器。.zip

    本项目以C++为基础,旨在实现一套线程安全的容器类,可能包括线程安全的栈、队列、列表或其他容器。这些容器通常会利用C++的互斥量(mutex)、条件变量(condition variable)等同步原语来保证在多线程环境下的正确...

    Java多线程与线程安全实践-基于Http协议的断点续传

    线程安全是多线程编程中的一个重要概念,指的是在多线程环境下,一个类或者对象的行为不会因为线程的并发访问而导致不正确的结果。在Java中,我们通常通过以下几种方式来保证线程安全: 1. **同步机制**:包括`...

    Java 多线程 订票 示例 线程安全

    在Java中,实现线程安全的方法通常包括同步机制(synchronized关键字)、volatile变量、Lock接口及其实现、原子类(Atomic*)等。 现在,让我们来看一个简单的订票系统的Java多线程示例。假设我们有一个票务系统,...

    java线程安全以及生产者消费者demo

    2. **原子操作**:Java的`java.util.concurrent.atomic`包提供了一系列原子类,如`AtomicInteger`,它们支持原子性的读/修改/写操作,避免了线程间的竞争。 3. **线程局部变量**:`ThreadLocal`类可以为每个线程...

    day33线程安全代码块设计思路_线程代码安全块_源码

    线程安全指的是当多个线程同时执行时,一个类或者方法能够正确处理并发调用,保证其内部数据的一致性和完整性。在Java中,如果一个方法或代码块被`synchronized`修饰,那么它将被视为线程安全的,因为只有一个线程能...

    第一节(多线程通讯代码演示及解决线程安全问题)

    合理设计线程的生命周期,避免长时间运行的线程阻塞其他线程,或者过早地释放资源。 在实际编程中,我们还应遵循一些最佳实践,例如,尽量减少共享状态,使用不可变对象,使用局部变量代替共享变量,以及尽可能使用...

    CVI 04.多线程数据保护(安全变量

    常见的安全变量包括互斥量(Mutex)、信号量(Semaphore)、条件变量(Condition Variable)以及原子操作(Atomic Operations)。 1. **互斥量**:互斥量是一种同步原语,用于确保同一时间只有一个线程能访问特定的...

    Java多线程-线程安全问题练习题

    3. **原子操作类**:如`java.util.concurrent.atomic`包中的类,提供原子性操作,避免了线程安全问题。 4. **线程局部变量**:`ThreadLocal`类,为每个线程提供独立的变量副本,避免了共享状态的问题。 5. **并发...

    Java多线程与线程安全实践-基于Http协议.zip

    Java提供了一些机制来保证线程安全,如同步机制(`synchronized`关键字)、锁(`java.util.concurrent.locks`包)、原子变量(`java.util.concurrent.atomic`包)以及并发工具类(如`Semaphore`、`CyclicBarrier`等...

    iOS线程读写安全

    2. 利用@atomic属性,为Swift中的结构体或枚举提供线程安全的读写操作。 3. 使用NSLock、NSCondition、NSConditionLock等锁对象进行手动同步。 4. 使用dispatch_barrier_sync或dispatch_barrier_async在GCD中创建...

    java线程安全总结

    `java.util.concurrent.atomic`包中提供了一系列的原子类,如`AtomicInteger`、`AtomicLong`等,它们提供了线程安全的整型和长整型操作,可以避免使用锁带来的性能开销。 #### 四、Java并发包的应用 Java并发包(`...

    线程方法操作

    例如`Atomic`类提供原子操作,`Collections.synchronizedXXX`方法返回线程安全的集合。 9. **中断线程** 通过`interrupt()`方法可以中断一个线程,但需要注意,这并不会立即停止线程,而是设置一个中断标志,线程...

    JAVA多线程教材

    线程安全的类如Atomic系列类和Collections.synchronizedXXX()方法可以帮助我们实现这一点。 9. **线程性能调优**:优化多线程程序涉及许多方面,包括合理设置线程数量、避免过度同步、减少上下文切换、使用适当的...

    多线程之间的线程通信

    1. **信号量(Semaphore)**:用于控制对共享资源的访问,当资源可用时,信号量值会减一,当资源不足时,线程会被阻塞,直到信号量值增加到允许访问为止。 2. **锁(Lock)**:包括互斥锁(Mutex)和读写锁(RW-Lock)。...

    Java多线程与线程安全实践-基于Http协议的断点续传.zip

    Java多线程与线程安全在开发中是至关重要的概念,尤其在处理大规模并发和高效资源利用时。断点续传技术则是网络传输中的优化手段,常见于大文件下载,可以提高用户体验并节省网络资源。本实践案例将结合这两者,讲解...

    线程异步工作,当一个线程结束时异步通知另一线程

    如果任务尚未完成,调用`get()`会阻塞当前线程,直到任务完成。 2. **std::promise与std::future** `std::promise`是C++11引入的另一个类,它提供了设置异步任务结果的能力。创建一个`std::promise`实例,然后通过...

    Java 线程的学习和使用

    5. volatile和Atomic类:提供原子操作,保证多线程环境下的数据一致性。 线程安全是Java多线程编程中的重要考虑因素,合理的线程管理和同步机制可以避免数据错误和程序崩溃。在实际应用中,如QQ聊天、网页访问等...

Global site tag (gtag.js) - Google Analytics