营销网站的关键字,wordpress 漏洞利用,太原做网站要多少钱呢,wordpress主题文章页面不显示图片写在前面
本文一起来看下使用JUC包的AtomicXxxxFieldUpdater实现更新的原子性。代码位置如下#xff1a; 当前有针对int#xff0c;long#xff0c;ref三种类型的支持。如果你需要其他类型的支持的话#xff0c;也可以照葫芦画瓢。
1#xff1a;例子
1.1#xff1a;普…写在前面
本文一起来看下使用JUC包的AtomicXxxxFieldUpdater实现更新的原子性。代码位置如下 当前有针对intlongref三种类型的支持。如果你需要其他类型的支持的话也可以照葫芦画瓢。
1例子
1.1普通方式
程序
package x;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;public class NormalUpdaterTest {CountDownLatch countDownLatch new CountDownLatch(1);public static void main(String[] args) throws InterruptedException {Account account new Account(0);ListThread list new ArrayList();for (int i 0; i 20; i) {Thread t new Thread(new Task(account));list.add(t);t.start();}for (Thread t : list) {t.join();}System.out.println(account.toString());}private static class Task implements Runnable {private Account account;Task(Account account) {this.account account;}Overridepublic void run() {for (int i 0; i 5; i) {try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}account.increMoney();}}}static class Account {private volatile int money;public Account(int initial) {this.money initial;}public void increMoney() {money;}public int getMoney() {return money;}Overridepublic String toString() {return Account{ money money };}}
}我们期望的结果是100但结果往往是比100小的因为整个操作过程并不是线程安全的根本原因是这个i它不是原子的而是三步走首先拿到i接着对i1最后将i1的结果写回内存所以大概率存在盖结果情况发生运行如下
Account{money91}Process finished with exit code 0当然这个结果并不是固定不变因为存在偶然性但一般都是小于100的。
1.2原子方式
package x;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;public class FieldlUpdaterTest {CountDownLatch countDownLatch new CountDownLatch(1);public static void main(String[] args) throws InterruptedException {Account account new Account(0);ListThread list new ArrayList();for (int i 0; i 20; i) {Thread t new Thread(new Task(account));list.add(t);t.start();}for (Thread t : list) {t.join();}System.out.println(account.toString());}private static class Task implements Runnable {private Account account;Task(Account account) {this.account account;}Overridepublic void run() {for (int i 0; i 5; i) {try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}account.increMoney();}}}static class Account {private volatile int money;private AtomicIntegerFieldUpdater fieldUpdater AtomicIntegerFieldUpdater.newUpdater(Account.class, money);public Account(int initial) {this.money initial;}public void increMoney() {
// money;
// fieldUpdater.incrementAndGet(money);// 以原子的方式更新this的moneyfieldUpdater.incrementAndGet(this);}public int getMoney() {return money;}Overridepublic String toString() {return Account{ money money };}}
}相比于普通方式增加了AtomicIntegerFieldUpdater fieldUpdater专门用来负责更新更新逻辑也对应的变为fieldUpdater.incrementAndGet(this);这个时候再运行
Account{money100}Process finished with exit code 0就对了因为此时加了cas的乐观锁。
2源码分析
首先看下代码AtomicIntegerFieldUpdater fieldUpdater AtomicIntegerFieldUpdater.newUpdater(Account.class, money);:
AtomicIntegerFieldUpdaterImpl(final ClassT tclass,final String fieldName,final Class? caller) {final Field field;final int modifiers;try {...} catch (Exception ex) {throw new RuntimeException(ex);}...// 获取要更新的类和字段的内存偏移量this.cclass (Modifier.isProtected(modifiers) tclass.isAssignableFrom(caller) !isSamePackage(tclass, caller))? caller : tclass;this.tclass tclass;this.offset U.objectFieldOffset(field);
}代码fieldUpdater.incrementAndGet(this);:
// java.util.concurrent.atomic.AtomicIntegerFieldUpdater.AtomicIntegerFieldUpdaterImpl#getAndAdd
public final int getAndAdd(T obj, int delta) {accessCheck(obj);// 基于偏移量完成更新其中getAndAddInt是cas的return U.getAndAddInt(obj, offset, delta);
}// sun.misc.Unsafe#getAndAddIntsun.misc.Unsafe#getAndAddInt
public final int getAndAddInt(Object var1, long var2, int var4) {int var5;do {var5 this.getIntVolatile(var1, var2);} while(!this.compareAndSwapInt(var1, var2, var5, var5 var4));return var5;
}注意代码} while(!this.compareAndSwapInt(var1, var2, var5, var5 var4));当compare不成功的时候就会返回false会尝试再次做1操作即自旋直到成功。
3相比于AtomicXxx的优势
更小的内存占用为什么呢?比如如下代码
class Account {private volatile int money;
}如果改造为AtomicInteger的方式则为
class Account {private volatile AtomicInteger money new AtomicInteger(0);
}AtomicInteger money的大小在不考虑padding的情况下大概为16字节对象头4字节的对象内容即20个字节那么创建100个对象大小就是2000个字节但如果是使用AtomicXxxFieldUpdater的代码就如下 private volatile int money;private static AtomicIntegerFieldUpdater fieldUpdater AtomicIntegerFieldUpdater.newUpdater(Account.class, money);
}这里我们简单的假定AtomicIntegerFieldUpdater fieldUpdater的大小是24个字节int money的大小是4个字节。此时我们创建100个对象money和fieldUpdater占用的大小就是4*10024即424因为fieldUpdater是静态的所以只有独一份。 可以看到AtomicIntegerFieldUpdater的方式占用了比AtomicInteger少得多的内存而占用更少的内存也意味着你的程序不需要申请更多的内存所以程序执行的速度也会更快。
写在后面
参考文章列表
jvm之对象大小分析。
多线程之JUC 。