淺析Java中的原子操做java
http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/src/share/classes/sun/misc/Unsafe.java編程
http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/tip/src/share/vm/prims/unsafe.cppjson
http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/sun/misc/Unsafe.java數組
http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/tip/src/share/vm/prims/unsafe.cpp併發
案例代碼函數
package com.dsp.unsafe; import java.io.Serializable; import java.lang.reflect.Field; import java.util.Arrays; import java.util.concurrent.locks.ReentrantLock; import com.alibaba.fastjson.JSON; import com.dsp.json.Person; import sun.misc.Unsafe; @SuppressWarnings("restriction") public class UnsafeDemo { static class Test { private final int x; Test(int x) { this.x = x; System.out.println("Test ctor"); } int getX() { return x; } } public static void main(String[] args) throws InstantiationException, NoSuchFieldException { // 得到一個UnSafe實例 Unsafe unsafe = null; try { Field f = Unsafe.class.getDeclaredField("theUnsafe"); f.setAccessible(true); unsafe = (Unsafe) f.get(null); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } if (unsafe != null) { try { // 構造一個對象,且不調用其構造函數 Test test = (Test) unsafe.allocateInstance(Test.class); // 獲得一個對象內部屬性的地址 long x_addr = unsafe.objectFieldOffset(Test.class.getDeclaredField("x")); // 直接給此屬性賦值 unsafe.getAndSetInt(test, x_addr, 47); System.out.println(test.getX()); } catch (InstantiationException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } } // 經過地址操做數組 if (unsafe != null) { final int INT_BYTES = 4; int[] data = new int[10]; System.out.println(Arrays.toString(data)); long arrayBaseOffset = unsafe.arrayBaseOffset(int[].class); System.out.println("Array address is :" + arrayBaseOffset); long arrayBaseOffset2 = unsafe.arrayBaseOffset(double[].class); System.out.println("Array address is :" + arrayBaseOffset2); unsafe.putInt(data, arrayBaseOffset, 47); unsafe.putInt(data, arrayBaseOffset + INT_BYTES * 8, 43); System.out.println(Arrays.toString(data)); } // CAS if (unsafe != null) { Test test = (Test) unsafe.allocateInstance(Test.class); long x_addr = unsafe.objectFieldOffset(Test.class.getDeclaredField("x")); unsafe.getAndSetInt(test, x_addr, 47); unsafe.compareAndSwapInt(test, x_addr, 47, 78); System.out.println("After CAS:" + test.getX()); } } @SuppressWarnings("deprecation") public static void mainB(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); Unsafe UNSAFE = (Unsafe) theUnsafe.get(null); System.out.println(UNSAFE); byte[] data = new byte[10]; System.out.println(Arrays.toString(data)); int byteArrayBaseOffset = UNSAFE.arrayBaseOffset(byte[].class); System.out.println(byteArrayBaseOffset); UNSAFE.putByte(data, byteArrayBaseOffset, (byte) 1); UNSAFE.putByte(data, byteArrayBaseOffset + 5, (byte) 5); System.out.println(Arrays.toString(data)); UNSAFE.setMemory(data, byteArrayBaseOffset, 1, (byte) 2); UNSAFE.setMemory(data, byteArrayBaseOffset + 5, 1, (byte) 6); System.out.println(Arrays.toString(data)); } @SuppressWarnings({ "unused", "rawtypes" }) public static void mainA(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); Unsafe unsafe = (Unsafe) field.get(null); long allocateMemory = unsafe.allocateMemory(1024); long theUnsafeOffset = unsafe.staticFieldOffset(field); System.out.println(theUnsafeOffset); /******************************************************************************** * 獲取對象中某字段在內存中的偏移量 */ // 開始使用unsafe對象,分別找到Person對象中name屬性和age屬性的內存地址偏移量 // 首先是Person類中的name屬性,在內存中設定的偏移位置 Field field2 = Person.class.getDeclaredField("name"); // 一旦這個類實例化後,該屬性在內存中的偏移位置 long offset2 = unsafe.objectFieldOffset(field2); System.out.println("name offset = " + offset2); /* * 而後是Person類中的age屬性,在內存中設定的偏移位置 */ Field age3 = Person.class.getDeclaredField("age"); long ageOffset3 = unsafe.objectFieldOffset(age3); System.out.println("age offset = " + ageOffset3); /******************************************************************************** * 修改某個字段的數據 */ /* * 修改字段數據 */ Person person = new Person(); person.setName("dsp"); person.setAge(20); /* * 獲取age屬性的內存地址偏移量 */ Field ageField = Person.class.getDeclaredField("age"); long ageOffset = unsafe.objectFieldOffset(ageField); /* * 比較並修改值 一、須要修改的對象 二、更改屬性的內存偏移量 三、預期的值 四、設置的新值 */ if (unsafe.compareAndSwapInt(person, ageOffset, 20, 26)) { System.out.println("修改數據成功"); } else { System.out.println("修改數據失敗"); } System.out.println(JSON.toJSONString(person)); int ss, ts; try { Class<Segment[]> sc = Segment[].class; SBASE = unsafe.arrayBaseOffset(sc); ss = unsafe.arrayIndexScale(sc); } catch (Exception e) { throw new Error(e); } SSHIFT = 31 - Integer.numberOfLeadingZeros(ss); System.out.println("SBASE=" + SBASE); System.out.println("ss=" + ss); System.out.println("SSHIFT=" + SSHIFT); int ARRAY_INT_BASE_OFFSET = unsafe.arrayBaseOffset(int[].class); int ARRAY_INT_INDEX_SCALE = unsafe.arrayIndexScale(int[].class); System.out.println("ARRAY_INT_BASE_OFFSET=" + ARRAY_INT_BASE_OFFSET); System.out.println("ARRAY_INT_INDEX_SCALE=" + ARRAY_INT_INDEX_SCALE); } // Unsafe mechanics private static long SBASE; private static long SSHIFT; static final class Segment<K, V> extends ReentrantLock implements Serializable { /* * Segments maintain a table of entry lists that are always kept in a consistent * state, so can be read (via volatile reads of segments and tables) without * locking. This requires replicating nodes when necessary during table * resizing, so the old lists can be traversed by readers still using old * version of table. * * This class defines only mutative methods requiring locking. Except as noted, * the methods of this class perform the per-segment versions of * ConcurrentHashMap methods. (Other methods are integrated directly into * ConcurrentHashMap methods.) These mutative methods use a form of controlled * spinning on contention via methods scanAndLock and scanAndLockForPut. These * intersperse tryLocks with traversals to locate nodes. The main benefit is to * absorb cache misses (which are very common for hash tables) while obtaining * locks so that traversal is faster once acquired. We do not actually use the * found nodes since they must be re-acquired under lock anyway to ensure * sequential consistency of updates (and in any case may be undetectably * stale), but they will normally be much faster to re-locate. Also, * scanAndLockForPut speculatively creates a fresh node to use in put if no node * is found. */ private static final long serialVersionUID = 2249069246763182397L; /** * The maximum number of times to tryLock in a prescan before possibly blocking * on acquire in preparation for a locked segment operation. On multiprocessors, * using a bounded number of retries maintains cache acquired while locating * nodes. */ static final int MAX_SCAN_RETRIES = Runtime.getRuntime().availableProcessors() > 1 ? 64 : 1; } }
:)post