CompareAndSwap原子操作原理
生活随笔
收集整理的這篇文章主要介紹了
CompareAndSwap原子操作原理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在翻閱AQS(AbstractQueuedSynchronizer)類的過程中,發現其進行原子操作的時候采用的是CAS。涉及的代碼如下:
1: private static final Unsafe unsafe = Unsafe.getUnsafe(); 2: private static final long stateOffset; 3: private static final long headOffset; 4: private static final long tailOffset; 5: private static final long waitStatusOffset; 6: private static final long nextOffset; 7: ? 8: static { 9: try { 10: stateOffset = unsafe.objectFieldOffset 11: (AbstractQueuedSynchronizer.class.getDeclaredField("state")); 12: headOffset = unsafe.objectFieldOffset 13: (AbstractQueuedSynchronizer.class.getDeclaredField("head")); 14: tailOffset = unsafe.objectFieldOffset 15: (AbstractQueuedSynchronizer.class.getDeclaredField("tail")); 16: waitStatusOffset = unsafe.objectFieldOffset 17: (Node.class.getDeclaredField("waitStatus")); 18: nextOffset = unsafe.objectFieldOffset 19: (Node.class.getDeclaredField("next")); 20: ? 21: } catch (Exception ex) { throw new Error(ex); } 22: } 23: ? 24: /** 25: * CAS head field. Used only by enq. 26: */ 27: private final boolean compareAndSetHead(Node update) { 28: return unsafe.compareAndSwapObject(this, headOffset, null, update); 29: } 30: ? 31: /** 32: * CAS tail field. Used only by enq. 33: */ 34: private final boolean compareAndSetTail(Node expect, Node update) { 35: return unsafe.compareAndSwapObject(this, tailOffset, expect, update); 36: } 37: ? 38: /** 39: * CAS waitStatus field of a node. 40: */ 41: private static final boolean compareAndSetWaitStatus(Node node, 42: int expect, 43: int update) { 44: return unsafe.compareAndSwapInt(node, waitStatusOffset, 45: expect, update); 46: } 47: ? 48: /** 49: * CAS next field of a node. 50: */ 51: private static final boolean compareAndSetNext(Node node, 52: Node expect, 53: Node update) { 54: return unsafe.compareAndSwapObject(node, nextOffset, expect, update); 55: }?
可以看到用到了compareAndSwapObject和compareAndSwapInt方法,那么究竟是怎么用其來實現原子操作的呢?
我們以compareAndSwapObject方法為例,其源碼大致如下:
1: UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) 2: UnsafeWrapper("Unsafe_CompareAndSwapObject"); 3: oop x = JNIHandles::resolve(x_h); //待更新的新值,也就是UpdateValue 4: oop e = JNIHandles::resolve(e_h); //期望值,也就是ExpectValue 5: oop p = JNIHandles::resolve(obj); //待操作對象 6: HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);//根據操作的對象和其在內存中的offset,計算出內存中具體位置 7: oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true);// 如果操作對象中的值和e期望值一致,則更新存儲值為x,反之不更新 8: jboolean success = (res == e); 9: if (success) //滿足更新條件 10: update_barrier_set((void*)addr, x); // 更新存儲值為x 11: return success; 12: UNSAFE_END從上述源碼可以看到,compareAndSwapObject方法中的第一個參數和第二個參數,用于確定待操作對象在內存中的具體位置的,然后取出值和第三個參數進行比較,如果相等,則將內存中的值更新為第四個參數的值,同時返回true,表明原子更新操作完畢。反之則不更新內存中的值,同時返回false,表明原子操作失敗。
同樣的,compareAndSwapInt方法也是相似的道理,第一個,第二個參數用來確定當前操作對象在內存中的存儲值,然后和第三個expect value比較,如果相等,則將內存值更新為第四個updaet value值。
由于原始的方法使用比較麻煩,所以在AQS中進行了封裝,大大簡化了操作:
1: private static final Unsafe unsafe = Unsafe.getUnsafe(); 2: private static final long stateOffset; 3: private static final long headOffset; 4: private static final long tailOffset; 5: private static final long waitStatusOffset; 6: private static final long nextOffset; 7: ? 8: static { 9: try { 10: stateOffset = unsafe.objectFieldOffset 11: (AbstractQueuedSynchronizer.class.getDeclaredField("state")); 12: headOffset = unsafe.objectFieldOffset 13: (AbstractQueuedSynchronizer.class.getDeclaredField("head")); 14: tailOffset = unsafe.objectFieldOffset 15: (AbstractQueuedSynchronizer.class.getDeclaredField("tail")); 16: waitStatusOffset = unsafe.objectFieldOffset 17: (Node.class.getDeclaredField("waitStatus")); 18: nextOffset = unsafe.objectFieldOffset 19: (Node.class.getDeclaredField("next")); 20: ? 21: } catch (Exception ex) { throw new Error(ex); } 22: } 23: ? 24: /** 25: * CAS head field. Used only by enq. 26: */ 27: private final boolean compareAndSetHead(Node update) { 28: return unsafe.compareAndSwapObject(this, headOffset, null, update); 29: } 30: ? 31: /** 32: * CAS tail field. Used only by enq. 33: */ 34: private final boolean compareAndSetTail(Node expect, Node update) { 35: return unsafe.compareAndSwapObject(this, tailOffset, expect, update); 36: } 37: ? 38: /** 39: * CAS waitStatus field of a node. 40: */ 41: private static final boolean compareAndSetWaitStatus(Node node, 42: int expect, 43: int update) { 44: return unsafe.compareAndSwapInt(node, waitStatusOffset, 45: expect, update); 46: } 47: ? 48: /** 49: * CAS next field of a node. 50: */ 51: private static final boolean compareAndSetNext(Node node, 52: Node expect, 53: Node update) { 54: return unsafe.compareAndSwapObject(node, nextOffset, expect, update); 55: }可以在其他項目中作為小模塊進行引入并使用。這樣使用起來就非常方便了:
1: ? 2: /** 3: * Creates and enqueues node for current thread and given mode. 4: * 5: * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared 6: * @return the new node 7: */ 8: private Node addWaiter(Node mode) { 9: Node node = new Node(Thread.currentThread(), mode); 10: // Try the fast path of enq; backup to full enq on failure 11: Node pred = tail; 12: if (pred != null) { 13: node.prev = pred; 14: if (compareAndSetTail(pred, node)) { 15: pred.next = node; 16: return node; 17: } 18: } 19: enq(node); 20: return node; 21: }?
總結
以上是生活随笔為你收集整理的CompareAndSwap原子操作原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: happens-before规则和as-
- 下一篇: spring boot redis 分布