今天写代码,尝试使用了AtomicInteger这个类,感觉使用起来很爽,特别适用于高并发访问,下面贴一个简单的例子:
- CashierContext类部分代码:
- private Map<String, AtomicInteger> counter = new HashMap<String, AtomicInteger>();
- private void initCounter() {
- counter.put("cvm", new AtomicInteger(0));
- }
- //被调用一次自动+1
- public MobileCashierViewModel getCvm() {
- if (cvm != null) {
- counter.get("cvm").incrementAndGet();
- }
- return cvm;
- }
使用场景:
因为通过WS服务获取MobileCashierViewModel 这个对象比较频繁,会很影响系统资源,可以将cvm存入缓存中,想要查看缓存cvm有多大价值,那么可以设置一个计数,来统记cvm被调用的次数
然后将CashierContext放入ThreadLocal中,然后再写一个过滤器,在过滤器里面可以得到获取这个服务从缓存中取的次数,这个就可以很容易看出来缓存价值。
那么为什么不使用记数器自加呢,例如count++这样的,因为这种计数是线程不安全的,高并发访问时统计会有误,而AtomicInteger为什么能够达到多而不乱,处理高并发应付自如呢,我们才看看AtomicInteger的源代码:
- private volatile int value;
大家可以看到有这个变量,value就是你设置的自加起始值。注意看它的访问控制符,是volatile,这个就是保证AtomicInteger线程安全的根源,熟悉并发的同学一定知道在java中处理并发主要有两种方式:
1,synchronized关键字,这个大家应当都各种面试和笔试中经常遇到。
2,volatile修饰符的使用,相信这个修饰符大家平时在项目中使用的也不是很多。
这里重点说一下volatile:
Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存重新读取该成员的值,而且,当成员变量值发生变化时,强迫将变化的值重新写入共享内存,这样两个不同的线程在访问同一个共享变量的值时,始终看到的是同一个值。
java语言规范指出:为了获取最佳的运行速度,允许线程保留共享变量的副本,当这个线程进入或者离开同步代码块时,才与共享成员变量进行比对,如果有变化再更新共享成员变量。这样当多个线程同时访问一个共享变量时,可能会存在值不同步的现象。
而volatile这个值的作用就是告诉VM:对于这个成员变量不能保存它的副本,要直接与共享成员变量交互。
建议:当多个线程同时访问一个共享变量时,可以使用volatile,而当访问的变量已在synchronized代码块中时,不必使用。
缺点:使用volatile将使得VM优化失去作用,导致效率较低,所以要在必要的时候使用。
相关推荐
在Java编程语言中,`volatile`关键字是一个非常重要的并发控制机制,它被用来修饰类的成员变量,确保这些变量在多线程环境下的可见性和有序性。然而,使用`volatile`并非总是如我们所期望的那样简单,有时会出现一些...
3. volatile修饰的变量,不允许线程内部缓存和重排序,而synchronized则可以保证线程之间的同步执行。 四、 Java中的原子类 1. AtomicInteger、AtomicLong、AtomicReference等,这些原子类提供了一些原子操作,...
1. 可见性:当一个变量被volatile修饰时,任何对这个变量的修改都会立即同步到主内存,其他线程在读取时会直接从主内存获取最新值,而不是依赖于本地缓存。这样保证了所有线程都能看到最新的修改。 2. 有序性:...
如果使用volatile修饰一个共享的计数器变量`count`,并有多个线程同时进行加一操作,由于这些操作不是原子的,所以可能会出现丢失更新的情况。为了解决这个问题,作者可能提到了使用synchronized或者Java并发包中的`...
这意味着即使`volatile`变量的读写操作是有序的,但它们与非`volatile`变量的交互仍可能存在不确定性。 **四、总结** 总的来说,`volatile`关键字在Java多线程编程中起到的关键作用是提供轻量级的同步机制,解决了...
使用volatile修饰的变量可以具有可见性,但不能保证它具有原子性。 2. 原子性:指一个操作是不可分割的,具有不可分割性。Java中的concurrent包下提供了一些原子类,如AtomicInteger、AtomicLong、AtomicReference等...
它确保了被`volatile`修饰的变量在任何线程中都具有最新的值,但并不保证线程安全,即不保证并发操作的原子性。 首先,我们要理解Java内存模型(JMM)。在JMM中,每个线程都有自己的工作内存,其中包含该线程使用到...
Java中的`volatile`关键字是用来修饰变量的,它主要用于解决多线程环境下的数据同步问题。在Java语言中,`volatile`变量提供了一种轻量级的同步机制,它确保了共享变量的可见性和有序性,但并不保证原子性。 **可见...
当一个变量被volatile修饰后,任何线程修改了该变量,其他线程都能立即看到这个变化。这避免了由于工作内存中缓存的旧值而导致的数据不一致问题。 3. **有序性**:Java允许编译器和处理器对指令进行重排序,这在单...
* 一个线程如何知道另一个线程修改了变量的方法:使用volatile修饰变量、synchronized修饰方法、wait/notify机制等。 2. synchronized关键字 * synchronized的作用:使得某个线程获取对象的锁,其他线程不能访问该...
在多线程环境下,为了优化性能,编译器和处理器可能会对指令进行重排序,但`volatile`变量的读写操作不会与其他操作重排序,保证了代码的执行顺序。这有助于避免数据一致性问题。 **不保证原子性**: 虽然`volatile...
1. **可见性**:当一个线程修改了`volatile`修饰的变量时,这个修改会立即同步到主内存,其他线程在下次访问该变量时能感知到这个变化。这意味着,一旦一个线程修改了`volatile`变量,其他所有线程都会看到这个最新...
1. **可见性**:当一个线程修改了volatile修饰的变量时,这个修改会立即对其他所有线程可见。这意味着,一旦一个线程修改了volatile变量,其他线程的高速缓存中对应的变量值会被立即刷新,保证了所有线程看到的都是...
在Java中,volatile是用于修饰字段的,它保证了被修饰的变量在多个线程之间的可见性,并且禁止指令重排序。这意味着,一旦一个线程修改了volatile变量的值,其他线程可以立即看到这个变化,而不需要额外的同步措施。...
例如,在VolatileTest类中,如果没有volatile修饰,b变量可能无法及时反映出a变量的变化,因为线程有自己的工作内存。而添加volatile后,其他线程在访问b时,会直接从主内存获取最新值,保证了可见性。 3. **信号量...
在多线程环境中,`volatile`关键字用于修饰变量,确保该变量的修改对所有线程都是可见的。这意味着,当一个线程修改了`volatile`变量后,其他线程能够立即看到这个修改,而无需额外的同步措施。这种特性解决了多线程...
当一个变量被`volatile`修饰时,它的写操作会立即刷新到主内存,读操作会直接从主内存读取,从而保证了不同线程间对这个变量的修改是可见的。例如,如果一个`volatile`变量`a`被设置为0,然后在一个线程中执行`a++`...
它是一个变量修饰符,只能用来修饰实例或静态变量,不能修饰方法或代码块。一个典型的例子是在单例模式的实现中,使用`volatile`关键字确保`singleton`变量在多线程环境下能正确初始化和访问,如以下代码所示: ```...
它确保了被修饰的变量在多线程环境下的可见性,即当一个线程修改了`volatile`变量的值,其他所有线程都能立即看到这一变化。这意味着,任何线程对`volatile`变量的修改都不会被隐藏或延迟,从而避免了数据不一致的...
如示例中提到的`i++`操作,即使使用`volatile`修饰,仍然可能出现线程安全问题,因为它实际上包含了三个步骤:读取、增加和写回,这些步骤不是原子性的。因此,如果需要保证复合操作的原子性,还需要配合`...