Java并发_volatile实现可见性但不保证原子性
生活随笔
收集整理的這篇文章主要介紹了
Java并发_volatile实现可见性但不保证原子性
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
讀后感介紹了volatile實現可見性的基本原理 介紹了volatile不能實現原子性的示例,volatile復合操作不能實現原子性,讀取值后在自增前改值可能被其它線程讀取并修改,自增后刷新值可能會覆蓋其它線程修改后的值 介紹了實現原子性的三種方法及示例 synchronized ?修飾對象
ReentrantLock 使用lock()、unlock()加鎖解鎖,比synchronized功能更多,JDK6后性能和synchronized差不多
AtomicInteger ?使用樂觀鎖
private?int?number?=?0;?? number++;?//不是原子操作?? import?java.util.concurrent.ExecutorService;?? import?java.util.concurrent.Executors;?? ?? /**? ?*?@author?InJavaWeTrust? ?*/?? public?class?TestSyn?implements?Runnable?{?? ?? ????private?int?number?=?0;?? ?? ????public?int?getNumber()?{?? ????????return?this.number;?? ????}?? ?? ????public?void?run()?{?? ????????increase();?? ????}?? ?? ????public?void?increase()?{?? ????????synchronized?(this)?{?? ????????????this.number++;?? ????????}?? ????}?? ?? ????public?static?void?main(String[]?args)?{?? ????????ExecutorService?exec?=?Executors.newFixedThreadPool(1000);?? ????????TestSyn?syn?=?new?TestSyn();?? ????????for?(int?i?=?0;?i?<?1000;?i++)?{?? ????????????exec.submit(syn);?? ????????}?? ????????System.out.println("number?:?"?+?syn.getNumber());?? ????????exec.shutdown();?? ????}?? }?? import?java.util.concurrent.ExecutorService;?? import?java.util.concurrent.Executors;?? import?java.util.concurrent.locks.Lock;?? import?java.util.concurrent.locks.ReentrantLock;?? /**? ?*?@author?InJavaWeTrust? ?*/?? public?class?TestRee?implements?Runnable?{?? ?? ????private?Lock?lock?=?new?ReentrantLock();?? ????private?int?number?=?0;?? ?? ????public?int?getNumber()?{?? ????????return?this.number;?? ????}?? ?? ????public?void?run()?{?? ????????increase();?? ????}?? ?? ????public?void?increase()?{?? ????????lock.lock();?? ????????try?{?? ????????????this.number++;?? ????????}?finally?{?? ????????????lock.unlock();?? ????????}?? ????}?? ?? ????public?static?void?main(String[]?args)?{?? ????????TestRee?ree?=?new?TestRee();?? ????????ExecutorService?exec?=?Executors.newFixedThreadPool(1000);?? ????????for?(int?i?=?0;?i?<?1000;?i++)?{?? ????????????exec.submit(ree);?? ????????}?? ????????System.out.println("number?:?"?+?ree.getNumber());?? ????????exec.shutdown();?? ????}?? }?? import?java.util.concurrent.ExecutorService;?? import?java.util.concurrent.Executors;?? import?java.util.concurrent.atomic.AtomicInteger;?? ?? /**? ?*?@author?InJavaWeTrust? ?*/?? public?class?TestAtomic?implements?Runnable?{?? ?? ????private?static?AtomicInteger?number?=?new?AtomicInteger(0);?? ?? ????public?void?run()?{?? ????????increase();?? ????}?? ?? ????public?void?increase()?{?? ????????number.getAndAdd(1);?? ????}?? ?? ????public?static?void?main(String[]?args)?{?? ????????TestAtomic?ato?=?new?TestAtomic();?? ????????ExecutorService?exec?=?Executors.newFixedThreadPool(1000);?? ????????for?(int?i?=?0;?i?<?1000;?i++)?{?? ????????????exec.submit(ato);?? ????????}?? ????????System.out.println("number?:?"?+?number.get());?? ????????exec.shutdown();?? ????}?? } ?
來自為知筆記(Wiz)
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
??volatile關鍵字:
- 能夠保證volatile變量的可見性
- 不能保證volatile變量復合操作的原子性
??volatile如何實現內存可見性:
???????? 深入來說:通過加入內存屏障和禁止重排序優化來實現的。
- 對volatile變量執行寫操作時,會在寫操作后加入一條store屏障指令
- 對volatile變量執行讀操作時,會在讀操作前加入一條load屏障指令
???????? 通俗地講:volatile變量在每次被線程訪問時,都強迫從主內存中重讀該變量的值,而當該變量發生變化時,又會強迫線程將最新的值刷新到主內存。這樣任何時刻,不同的線程總能看到該變量的最新值。
?
?????????線程寫volatile變量的過程:
- 改變線程工作內存中volatile變量副本的值
- 將改變后的副本的值從工作內存刷新到主內存
?????????線程讀volatile變量的過程:
- 從主內存中讀取volatile變量的最新值到線程的工作內存中
- 從工作內存中讀取volatile變量的副本
?????????volatile不能保證volatile變量復合操作的原子性:
Java代碼?????????? 它分為三步:
???????? 讀取number的值
???????? 將number的值加1
???????? 寫入最新的number的值
?
??????????保證number自增操作的原子性:
- 使用synchronized關鍵字
- 使用ReentrantLock
- 使用AtomicInteger
??????????使用synchronized關鍵字
Java代碼???
??????????使用ReentrantLock
Java代碼???
??????????使用AtomicInteger
Java代碼??來自為知筆記(Wiz)
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的Java并发_volatile实现可见性但不保证原子性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何在IAR工程中创建和使用模板
- 下一篇: WebStorm、PHPStorm、In