J.U.C 并发包提供了:
AtomicReferenceFieldUpdater // 域 字段
AtomicIntegerFieldUpdater
AtomicLongFieldUpdater
利用字段更新器,可以针对对象的某个域(Field)进行原子操作,只能配合 volatile 修饰的字段使用,否则会出现异常。
@Slf4j(topic = "c.Test40") public class Test40 { public static void main(String[] args) { Student stu = new Student(); AtomicReferenceFieldUpdater updater = AtomicReferenceFieldUpdater.newUpdater(Student.class, String.class, "name"); System.out.println(updater.compareAndSet(stu, null, "张三")); System.out.println(stu); } } class Student { volatile String name; @Override public String toString() { return "Student{" + "name='" + name + '\'' + '}'; } }
public class Test41 { public static void main(String[] args) { for (int i = 0; i < 5; i++) { demo( () -> new AtomicLong(0), (adder) -> adder.getAndIncrement() ); } for (int i = 0; i < 5; i++) { demo( () -> new LongAdder(), adder -> adder.increment() ); } } /* () -> 结果 提供累加器对象 (参数) -> 执行累加操作 */ private staticvoid demo(Supplier adderSupplier, Consumer {action) T adder = adderSupplier.get(); Listts = new ArrayList<>(); // 4 个线程,每人累加 50 万 for (int i = 0; i < 4; i++) { ts.add(new Thread(() -> { for (int j = 0; j < 500000; j++) { action.accept(adder); } })); } long start = System.nanoTime(); ts.forEach(t -> t.start()); ts.forEach(t -> { try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); } }); long end = System.nanoTime(); System.out.println(adder + " cost:" + (end - start) / 1000_000); } }性能提升的原因很简单,就是在有竞争的时,设置多个累加单元,Thread - 0 累加 Cell[0],而 Thread - 1 累加 Cell [1] ......最后将结果汇总。这样它们在累加时操作的不同的 Cell 变量,因此减少了 CAS 重试失败,从而提高性能。
- @Slf4j(topic = "c.Test42")
- public class LockCas {
- // 0 没加锁
- // 1 加锁
- private AtomicInteger state = new AtomicInteger(0);
-
- public void lock() {
- while (true) {
- if (state.compareAndSet(0, 1)) {
- break;
- }
- }
- }
-
- public void unlock() {
- log.debug("unlock...");
- state.set(0);
- }
-
- public static void main(String[] args) {
- LockCas lock = new LockCas();
- new Thread(() -> {
- log.debug("begin...");
- lock.lock();
- try {
- log.debug("lock...");
- sleep(1);
- } finally {
- lock.unlock();
- }
- }).start();
-
- new Thread(() -> {
- log.debug("begin...");
- lock.lock();
- try {
- log.debug("lock...");
- } finally {
- lock.unlock();
- }
- }).start();
- }
- }
缓存与内存的速度比较
(1)因为 CPU 与 内存的速度差异很大,需要靠预读数据至缓存来提升效率。(2)而缓存以缓存行为单位,每个缓存行对应着一块内存,一般是 64 byte ( 8 个 long )(3)缓存的加入会造成数据副本的产生,即同一份数据会缓存在不同核心的缓存行中(4)CPU 要保证数据的一致性,如果某个 CPU 核心更改了数据,其它 CPU 核心对应的整个缓存行必须失效
一些源码学习,下次再说吧。。。P177
Unsafe 对象提供了非常底层的,操作内存、线程的方法(这些非常的危险),Unsafe 对象不能直接调用,只能通过反射获取。
- public class TestUnsafe {
-
- public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
- Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
- theUnsafe.setAccessible(true);
- Unsafe unsafe = (Unsafe) theUnsafe.get(null);
-
- System.out.println(unsafe);
-
- // 1. 获取域的偏移地址
- long idOffset = unsafe.objectFieldOffset(Teacher.class.getDeclaredField("id"));
- long nameOffset = unsafe.objectFieldOffset(Teacher.class.getDeclaredField("name"));
-
- Teacher t = new Teacher();
- // 2. 执行 cas 操作
- unsafe.compareAndSwapInt(t, idOffset, 0, 1);
- unsafe.compareAndSwapObject(t, nameOffset, null, "张三");
-
- // 3. 验证
- System.out.println(t);
- }
- }
- @Data
- class Teacher {
- volatile int id;
- volatile String name;
- }
- @Slf4j(topic = "c.Test42")
- public class Test42 {
- public static void main(String[] args) {
- Account.demo(new MyAtomicInteger(10000));
- }
- }
-
- class MyAtomicInteger implements Account {
- private volatile int value;
- private static final long valueOffset;
- private static final Unsafe UNSAFE;
- static {
- UNSAFE = UnsafeAccessor.getUnsafe();// 自定义的方法获取unsafe
- try {
- valueOffset = UNSAFE.objectFieldOffset(MyAtomicInteger.class.getDeclaredField("value"));
- } catch (NoSuchFieldException e) {
- e.printStackTrace();
- throw new RuntimeException(e);
- }
- }
-
- public int getValue() {
- return value;
- }
-
- public void decrement(int amount) {
- while(true) {
- int prev = this.value;
- int next = prev - amount;
- if (UNSAFE.compareAndSwapInt(this, valueOffset, prev, next)) {
- break;
- }
- }
- }
-
- public MyAtomicInteger(int value) {
- this.value = value;
- }
-
- @Override
- public Integer getBalance() {
- return getValue();
- }
-
- @Override
- public void withdraw(Integer amount) {
- decrement(amount);
- }
- }