在保證執行緒安全的時候,除了synchronized和lock,也需要用到其他的一些關鍵字,可以針對不同的場景使用。
使用final修飾變數,表示變數只能被賦值一次,賦值之後值不再改變,因此使用final修飾基本資料型別的時候,自然就是執行緒安全的。
private final int value;
另外
final修飾類,表明這個類不能被繼承;
final修飾方法,表明這個方法不能被重寫;
如果final修飾並不是基本資料型別,如下面的例子所示:
final listlist = new arraylist<>();
list.add("123");
list.add("234");
system.out.println("list:"+list.get(0)+","+list.get(1));
雖然list變數被final修飾,但是所指的列表仍然是可以進行修改的;只不過經過final修飾,list變數不能夠再指向其他的記憶體。
被threadlocal修飾的關鍵字會在每個執行緒當中都會建立乙個變數的副本,這樣每個執行緒都會有各自的變數,自然不會產生執行緒安全的問題。
public static threadlocalstringlocal = new threadlocal();
public static void main(string args)
});thread thread2 = new thread(new runnable()
});try catch (exception e)
system.out.println("主線程:"+stringlocal.get());
}
在上面的**中,主線程給stringlocal賦了乙個初始值,執行緒1再給stringlocal賦值「thread1」,執行緒2直接輸出stringlocal,最終輸出如下
執行緒1:thread1
執行緒2:null
主線程:初始值
可以看到雖然三個執行緒都是對stringlocal進行操作,但是操作的物件並不相同。
主線程給stringlocal賦值,只能在主線程當中起作用;
而執行緒2沒有給stringlocal賦值,因此列印出來的就是空
volatile能保證被其修飾的變數發生改變時,其他的執行緒能夠立馬感知到;
對於普通變數a,當a的值發生改變時,a的值需要想主記憶體進行回寫,寫完之後,另外的執行緒才能夠感知到a的值已經發生了變化。
而對於被volatile修飾的變數b,當其他執行緒要使用變數b的時候,都要先重新整理。
但是volatile並不能夠保證執行緒安全,如下所示
public static volatile int value=0;
public static void main(string args)
public void run()
}
atomic採用的是樂觀鎖的策略,即不管執行緒安全,先進行操作,若沒有其他執行緒競爭,那我的操作就成功了,若有其他的執行緒競爭,產生了衝突,再採取補救的措施。
看下面這段**
public static atomicinteger value = new atomicinteger(0);
public static void main(string args)
}}
不斷嘗試將比當前值大1的新值賦值給自己,直至成功為止。
但是有乙個漏洞,若是新值經過一系列操作變得跟原來的值是一樣的,那麼就沒辦法判斷我的修改是否產生了作用。上面的這個場景當中沒有這個漏洞。
Linux 執行緒安全(二)
標頭檔案 include1.定義 sem t sem 2.初始化 sem init sem t sem,int pshared,int value sem 傳入訊號量的位址 pshared 0代表執行緒 1代表程序 value 實際資源個數,用於訊號量初始化3.等待 sem wait sem t s...
Java多執行緒系列(二) 執行緒安全
個人主頁 tuzhenyu s page 多執行緒併發操作下可能出現記憶體不可見問題,指令重排序問題,4位元組賦值問題等,主要造成執行緒不安全的還是記憶體不可見和指令重排序 非執行緒安全出現的情況主要是多執行緒同時對乙個共享可變變數進行讀寫操作,因此可以通過以下三種方法解決非執行緒安全問題 將可變變...
多執行緒二 多執行緒安全問題
當多個執行緒共享同乙個全域性或者靜態變數,做寫的操作,可能會發生資料衝突問題,也就是執行緒安全問題。讀操作和區域性變數是不會發生的。二 執行緒安全的解決方法 該資源只能讓當前執行緒操作,操作完成之後,再讓其他執行緒執行 多執行緒之間同步 synchronized 使用鎖 lock 語法 synchr...