`

AtomicInteger与Volatile修饰

 
阅读更多

今天写代码,尝试使用了AtomicInteger这个类,感觉使用起来很爽,特别适用于高并发访问,下面贴一个简单的例子:

Java代码  收藏代码
  1. CashierContext类部分代码:  
  2.   
  3. private Map<String, AtomicInteger> counter          = new HashMap<String, AtomicInteger>();  
  4.   
  5.   
  6. private void initCounter() {  
  7.      counter.put("cvm"new AtomicInteger(0));  
  8. }  
  9.   
  10. //被调用一次自动+1  
  11.   
  12. public MobileCashierViewModel getCvm() {  
  13.   
  14.         if (cvm != null) {  
  15.             counter.get("cvm").incrementAndGet();  
  16.         }  
  17.         return cvm;  
  18.     }  

 

使用场景:

因为通过WS服务获取MobileCashierViewModel 这个对象比较频繁,会很影响系统资源,可以将cvm存入缓存中,想要查看缓存cvm有多大价值,那么可以设置一个计数,来统记cvm被调用的次数

 

 

然后将CashierContext放入ThreadLocal中,然后再写一个过滤器,在过滤器里面可以得到获取这个服务从缓存中取的次数,这个就可以很容易看出来缓存价值。

 

那么为什么不使用记数器自加呢,例如count++这样的,因为这种计数是线程不安全的,高并发访问时统计会有误,而AtomicInteger为什么能够达到多而不乱,处理高并发应付自如呢,我们才看看AtomicInteger的源代码:

 

 

Java代码  收藏代码
  1. private volatile int value;  

 

 

大家可以看到有这个变量,value就是你设置的自加起始值。注意看它的访问控制符,是volatile,这个就是保证AtomicInteger线程安全的根源,熟悉并发的同学一定知道在java中处理并发主要有两种方式:

1,synchronized关键字,这个大家应当都各种面试和笔试中经常遇到。

2,volatile修饰符的使用,相信这个修饰符大家平时在项目中使用的也不是很多。

 

这里重点说一下volatile:

Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存重新读取该成员的值,而且,当成员变量值发生变化时,强迫将变化的值重新写入共享内存,这样两个不同的线程在访问同一个共享变量的值时,始终看到的是同一个值。

 

java语言规范指出:为了获取最佳的运行速度,允许线程保留共享变量的副本,当这个线程进入或者离开同步代码块时,才与共享成员变量进行比对,如果有变化再更新共享成员变量。这样当多个线程同时访问一个共享变量时,可能会存在值不同步的现象。

 

而volatile这个值的作用就是告诉VM:对于这个成员变量不能保存它的副本,要直接与共享成员变量交互。

 

建议:当多个线程同时访问一个共享变量时,可以使用volatile,而当访问的变量已在synchronized代码块中时,不必使用。

缺点:使用volatile将使得VM优化失去作用,导致效率较低,所以要在必要的时候使用。

分享到:
评论
1 楼 无心流泪wan 2015-08-28  
在多个并发写的情况下使用volatile变量是不安全的!!!!不然也就不会有AtomicInteger了

相关推荐

    Java并发编程(5)volatile变量修饰符-意料之外

    在Java编程语言中,`volatile`关键字是一个非常重要的并发控制机制,它被用来修饰类的成员变量,确保这些变量在多线程环境下的可见性和有序性。然而,使用`volatile`并非总是如我们所期望的那样简单,有时会出现一些...

    java里的volatile关键字详解

    3. volatile修饰的变量,不允许线程内部缓存和重排序,而synchronized则可以保证线程之间的同步执行。 四、 Java中的原子类 1. AtomicInteger、AtomicLong、AtomicReference等,这些原子类提供了一些原子操作,...

    16 让你眼见为实—volatile详解.pdf

    1. 可见性:当一个变量被volatile修饰时,任何对这个变量的修改都会立即同步到主内存,其他线程在读取时会直接从主内存获取最新值,而不是依赖于本地缓存。这样保证了所有线程都能看到最新的修改。 2. 有序性:...

    Java并发编程(18)第五篇中volatile意外问题的

    如果使用volatile修饰一个共享的计数器变量`count`,并有多个线程同时进行加一操作,由于这些操作不是原子的,所以可能会出现丢失更新的情况。为了解决这个问题,作者可能提到了使用synchronized或者Java并发包中的`...

    Java 多线程与并发(5-26)-关键字- volatile详解.pdf

    这意味着即使`volatile`变量的读写操作是有序的,但它们与非`volatile`变量的交互仍可能存在不确定性。 **四、总结** 总的来说,`volatile`关键字在Java多线程编程中起到的关键作用是提供轻量级的同步机制,解决了...

    深入了解Java中Volatile关键字

    使用volatile修饰的变量可以具有可见性,但不能保证它具有原子性。 2. 原子性:指一个操作是不可分割的,具有不可分割性。Java中的concurrent包下提供了一些原子类,如AtomicInteger、AtomicLong、AtomicReference等...

    Java里volatile关键字是什么意思

    它确保了被`volatile`修饰的变量在任何线程中都具有最新的值,但并不保证线程安全,即不保证并发操作的原子性。 首先,我们要理解Java内存模型(JMM)。在JMM中,每个线程都有自己的工作内存,其中包含该线程使用到...

    Java Volatile 变量详解及使用方法

    Java中的`volatile`关键字是用来修饰变量的,它主要用于解决多线程环境下的数据同步问题。在Java语言中,`volatile`变量提供了一种轻量级的同步机制,它确保了共享变量的可见性和有序性,但并不保证原子性。 **可见...

    学习Java多线程之volatile域

    当一个变量被volatile修饰后,任何线程修改了该变量,其他线程都能立即看到这个变化。这避免了由于工作内存中缓存的旧值而导致的数据不一致问题。 3. **有序性**:Java允许编译器和处理器对指令进行重排序,这在单...

    并发编程 70 道面试题及答案.docx

    * 一个线程如何知道另一个线程修改了变量的方法:使用volatile修饰变量、synchronized修饰方法、wait/notify机制等。 2. synchronized关键字 * synchronized的作用:使得某个线程获取对象的锁,其他线程不能访问该...

    一文读懂ava中的Volatile关键字使用

    在多线程环境下,为了优化性能,编译器和处理器可能会对指令进行重排序,但`volatile`变量的读写操作不会与其他操作重排序,保证了代码的执行顺序。这有助于避免数据一致性问题。 **不保证原子性**: 虽然`volatile...

    Java实习生面试复习(八):volatile的学习

    1. **可见性**:当一个线程修改了`volatile`修饰的变量时,这个修改会立即同步到主内存,其他线程在下次访问该变量时能感知到这个变化。这意味着,一旦一个线程修改了`volatile`变量,其他所有线程都会看到这个最新...

    Java并发编程:volatile关键字详细解析

    1. **可见性**:当一个线程修改了volatile修饰的变量时,这个修改会立即对其他所有线程可见。这意味着,一旦一个线程修改了volatile变量,其他线程的高速缓存中对应的变量值会被立即刷新,保证了所有线程看到的都是...

    04 并发编程专题04.zip

    在Java中,volatile是用于修饰字段的,它保证了被修饰的变量在多个线程之间的可见性,并且禁止指令重排序。这意味着,一旦一个线程修改了volatile变量的值,其他线程可以立即看到这个变化,而不需要额外的同步措施。...

    Java 并发编程:volatile的使用及其原理解析

    例如,在VolatileTest类中,如果没有volatile修饰,b变量可能无法及时反映出a变量的变化,因为线程有自己的工作内存。而添加volatile后,其他线程在访问b时,会直接从主内存获取最新值,保证了可见性。 3. **信号量...

    java代码-volatile原子性

    在多线程环境中,`volatile`关键字用于修饰变量,确保该变量的修改对所有线程都是可见的。这意味着,当一个线程修改了`volatile`变量后,其他线程能够立即看到这个修改,而无需额外的同步措施。这种特性解决了多线程...

    Java中Volatile关键字步骤

    当一个变量被`volatile`修饰时,它的写操作会立即刷新到主内存,读操作会直接从主内存读取,从而保证了不同线程间对这个变量的修改是可见的。例如,如果一个`volatile`变量`a`被设置为0,然后在一个线程中执行`a++`...

    Java Volatile关键字实现原理过程解析

    它是一个变量修饰符,只能用来修饰实例或静态变量,不能修饰方法或代码块。一个典型的例子是在单例模式的实现中,使用`volatile`关键字确保`singleton`变量在多线程环境下能正确初始化和访问,如以下代码所示: ```...

    谈谈Java中Volatile关键字的理解

    它确保了被修饰的变量在多线程环境下的可见性,即当一个线程修改了`volatile`变量的值,其他所有线程都能立即看到这一变化。这意味着,任何线程对`volatile`变量的修改都不会被隐藏或延迟,从而避免了数据不一致的...

    Java开发中的volatile你必须要了解一下

    如示例中提到的`i++`操作,即使使用`volatile`修饰,仍然可能出现线程安全问题,因为它实际上包含了三个步骤:读取、增加和写回,这些步骤不是原子性的。因此,如果需要保证复合操作的原子性,还需要配合`...

Global site tag (gtag.js) - Google Analytics