修改对象的字段

  1. package org.example.concurrency.test;
  2. import lombok.Data;
  3. import sun.misc.Unsafe;
  4. import java.lang.reflect.Constructor;
  5. import java.lang.reflect.Field;
  6. /**
  7. * @author huskyui
  8. */
  9. public class Test33 {
  10. public static void main(String[] args) throws Exception {
  11. Class<?> aClass = Class.forName("sun.misc.Unsafe");
  12. Constructor<?> declaredConstructor = aClass.getDeclaredConstructors()[0];
  13. declaredConstructor.setAccessible(true);
  14. Unsafe unsafe = (Unsafe)declaredConstructor.newInstance(new Object[0]);
  15. System.out.println(unsafe);
  16. Student student = new Student();
  17. Field id = Student.class.getDeclaredField("id");
  18. Field name = Student.class.getDeclaredField("name");
  19. long idOffset = unsafe.objectFieldOffset(id);
  20. long nameOffset = unsafe.objectFieldOffset(name);
  21. boolean b = unsafe.compareAndSwapInt(student, idOffset, 0, 1);
  22. System.out.println(unsafe.compareAndSwapObject(student, nameOffset, null, "huskyui"));
  23. System.out.println(b);
  24. System.out.println(student);
  25. }
  26. }
  27. @Data
  28. class Student{
  29. volatile int id;
  30. volatile String name;
  31. }

Unsafe需要通过反射反射获取对象。修改对象字段的时候,需要获得字段的offset值

实现一个原子类

  1. package org.example.concurrency.test;
  2. import sun.misc.Unsafe;
  3. import java.lang.reflect.Constructor;
  4. import java.util.ArrayList;
  5. import java.util.List;
  6. /**
  7. * @author huskyui
  8. */
  9. public class MyAtomicInteger {
  10. private volatile int data;
  11. static Unsafe unsafe = null;
  12. static long DATA_OFFSET = 0;
  13. static {
  14. try {
  15. Class<?> aClass = Class.forName("sun.misc.Unsafe");
  16. Constructor<?> declaredConstructor = aClass.getDeclaredConstructors()[0];
  17. declaredConstructor.setAccessible(true);
  18. unsafe = (Unsafe) declaredConstructor.newInstance(new Object[0]);
  19. System.out.println(unsafe);
  20. DATA_OFFSET = unsafe.objectFieldOffset(MyAtomicInteger.class.getDeclaredField("data"));
  21. }catch (Exception e){
  22. e.printStackTrace();
  23. }
  24. }
  25. public MyAtomicInteger(int data) {
  26. this.data = data;
  27. }
  28. public int get(){
  29. return data;
  30. }
  31. public void decrease(int amount){
  32. while (true) {
  33. int prev = get();
  34. int next = prev - amount;
  35. if (unsafe.compareAndSwapInt(this, DATA_OFFSET, prev, next)){
  36. break;
  37. }
  38. }
  39. }
  40. public static void main(String[] args) {
  41. MyAtomicInteger myAtomicInteger = new MyAtomicInteger(10000);
  42. long start = System.nanoTime();
  43. List<Thread> ts = new ArrayList<>();
  44. for (int i = 0;i<1000;i++){
  45. ts.add(new Thread(()->{
  46. myAtomicInteger.decrease(10);
  47. }));
  48. }
  49. ts.forEach(Thread::start);
  50. for (Thread t : ts) {
  51. try {
  52. t.join();
  53. } catch (InterruptedException e) {
  54. e.printStackTrace();
  55. }
  56. }
  57. long cost = System.nanoTime()-start;
  58. System.out.println("cost" + (cost/1000/10000)+ " amount" + myAtomicInteger.get());
  59. }
  60. }