一、複習
synchronized和volatile的不同點,相同點 volatile不能保證原子性,只能保證內存可見性 volatile在什麼情況下可以使用(兩種情況) ABA問題定義,產生原因以及消除方法 Java中的CAS操作 unsafe類中的boolean objectFieldOffset(Field field),boolean compareAndSwapLong(Object obj,long offset,long expect,long update),int arrayBaseOffset(Class arrayClass),int arrayIndexOffset(Class arrayClass)
二、Unsafe類中的其他方法
1.public native long getLongvolatile(Object obj,long offset)
該方法用於獲取對象obj地址偏移量爲offset長度的對應volatile語義的值
2.void putLongvolatile(Object obj,long offset,long value)
該方法用於在對象obj地址偏移量爲offset長度的類型爲long的field值設置爲value,支持volatile
3.void putOrderedLong(Object obj,long offset,long value)
該方法用於在對象obj地址偏移量爲offset長度的類型爲long的field值設置爲value,這是一個有延遲的putLongvolatile方法,並且不能保證其他線程也能看到,只有被volatile修飾並有可能被意外修改的時候纔會使用這個方法
4.void park(boolean isAbsolute,long time)
如果isAbsolute爲false,time=0,表示當前線程一直阻塞 如果isAbsolute爲false,time>0,表示當前線程阻塞time時間後,會被喚醒
注意:這時的time是一個時間段,也就是調用開始到time用完
如果isAbsolute爲true,time>=0,表示當前線程time時間後阻塞停止,被喚醒,這裏的time是絕對時間,會換算稱ms單位的一個時間點 另外當其他線程調用了該線程的nterrupt()方法之後,該線程會返回; 如果其他線程調用了unpark方法,並且把該線程作爲參數傳入unpark方法中,那麼該線程也會返回
5.void unpark(Thread thread)
喚醒調用park方法的阻塞狀態的thread線程。
6.long getAndSetLong(Object obj,long offset,long update)
獲取對象obj中偏移量爲offset的變量volatile語義的當前值,並且設置volatile語義的值爲update
public final long getAndSetLong(Object obj,long offset,long update){
long l;
do{
l=getLongvolatile(obj,offset);
}while(!compareAndSwapLong(obj,offset,l,update);
return l;
}
這裏的循環是考慮到在多線程的環境下CAS操作會出現失敗的情況,因此多次判斷一下獲取正確的值
7.long getAndAddLong(Object obj,long offset,long addValue)
該函數用於獲取對象obj在其偏移量爲offset的volatile變量的語義,並且該值賦值爲原值加addValue
public final long getAndAddLong(Object obj,long offset,long addValue){
long l;
do{
l = getLongvolatile(obj,offset);
}while(!compareAndSwapLong(obj,offset,l,l+addValue);
return l;
}
三、直接對Unsafe類舉例
package com.ruigege.OtherFoundationOfConcurrent2;
import jdk.internal.misc.Unsafe;
public class TestUnsafe {
static final Unsafe unsafe = Unsafe.getUnsafe();
static final long state = 0;
static final long stateOffset=0;
//unsafe實例內部屬性state的偏移量
static {
try {
stateOffset = unsafe.objectFieldOffset(Unsafe.class.getDeclaredField("state"));
}catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
TestUnsafe testUnsafe = new TestUnsafe();
Boolean success = unsafe.compareAndSwapInt(testUnsafe,stateOffset,0,1);
System.out.println(success);
}
}
基本符合預期
四 、源碼:
所在包:com.ruigege.OtherFoundationOfConcurrent2 https://github.com/ruigege66/ConcurrentJava
CSDN:https://blog.csdn.net/weixin_44630050 博客園:https://www.cnblogs.com/ruigege0000/ 歡迎關注微信公衆號:傅里葉變換,個人賬號,僅用於技術交流