日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java 原子锁

發(fā)布時(shí)間:2023/12/20 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 原子锁 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
研究ThreadPoolExecutor的時(shí)候,發(fā)現(xiàn)其中大量使用了volatile變量。?
不知為何,因此做了一番查找,研究:?

其中借鑒了很多網(wǎng)上資料。?

在了解volatile變量作用前,先需要明白一些概念:?

什么是原子操作??
所謂原子操作,就是"不可中斷的一個(gè)或一系列操作" , 在確認(rèn)一個(gè)操作是原子的情況下,多線程環(huán)境里面,我們可以避免僅僅為保護(hù)這個(gè)操作在外圍加上性能昂貴的鎖,甚至借助于原子操作,我們可以實(shí)現(xiàn)互斥鎖。?
很多操作系統(tǒng)都為int類型提供了+-賦值的原子操作版本,比如 NT 提供了 InterlockedExchange 等API, Linux/UNIX也提供了atomic_set 等函數(shù)。?



關(guān)于java中的原子性??
原子性可以應(yīng)用于除long和double之外的所有基本類型之上的“簡單操作”。對(duì)于讀取和寫入出long和double之外的基本類型變量這樣的操作,可以保證它們會(huì)被當(dāng)作不可分(原子)的操作來操作。?
因?yàn)镴VM的版本和其它的問題,其它的很多操作就不好說了,比如說++操作在C++中是原子操作,但在Java中就不好說了。?
另外,Java提供了AtomicInteger等原子類。再就是用原子性來控制并發(fā)比較麻煩,也容易出問題。?

volatile原理是什么??
Java中volatile關(guān)鍵字原義是“不穩(wěn)定、變化”的意思?
使用volatile和不使用volatile的區(qū)別在于JVM內(nèi)存主存和線程工作內(nèi)存的同步之上。volatile保證變量在線程工作內(nèi)存和主存之間一致。?
其實(shí)是告訴處理器, 不要將我放入工作內(nèi)存, 請(qǐng)直接在主存操作我.?

接下來是測試 :(通過測試能更好的發(fā)現(xiàn)和分析問題)?
申明了幾種整形的變量,開啟100個(gè)線程同時(shí)對(duì)這些變量進(jìn)行++操作,發(fā)現(xiàn)結(jié)果差異很大:?
>>Execute End:?
>>Atomic: 100000?
>>VInteger: 38790?
>>Integer: 68749?
>>Source i: 99205?
>>Source Vi: 99286?
也就是說除了Atomic,其他的都是錯(cuò)誤的。?

我們通過一些疑問,來解釋一下。?

1:為什么會(huì)產(chǎn)生錯(cuò)誤的數(shù)據(jù)??
多線程引起的,因?yàn)閷?duì)于多線程同時(shí)操作一個(gè)整型變量在大并發(fā)操作的情況下無法做到同步,而Atom提供了很多針對(duì)此類線程安全問題的解決方案,因此解決了同時(shí)讀寫操作的問題。?
2:為什么會(huì)造成同步問題??
Java多線程在對(duì)變量進(jìn)行操作的時(shí)候,實(shí)際上是每個(gè)線程會(huì)單獨(dú)分配一個(gè)針對(duì)i值的拷貝(獨(dú)立內(nèi)存區(qū)域),但是申明的i值確是在主內(nèi)存區(qū)域中,當(dāng)對(duì)i值修改完畢后,線程會(huì)將自己內(nèi)存區(qū)域塊中的i值拷貝到主內(nèi)存區(qū)域中,因此有可能每個(gè)線程拿到的i值是不一樣的,從而出現(xiàn)了同步問題。?
3:為什么使用volatile修飾integer變量后,還是不行??
因?yàn)関olatile僅僅只是解決了存儲(chǔ)的問題,即i值只是保留在了一個(gè)內(nèi)存區(qū)域中,但是i++這個(gè)操作,涉及到獲取i值、修改i值、存儲(chǔ)i值(i=i+1),這里的volatile只是解決了存儲(chǔ)i值得問題,至于獲取和修改i值,確是沒有做到同步。?
4:既然不能做到同步,那為什么還要用volatile這種修飾符??
主要的一個(gè)原因是方便,因?yàn)橹恍杼砑右粋€(gè)修飾符即可,而無需做對(duì)象加鎖、解鎖這么麻煩的操作。但是本人不推薦使用這種機(jī)制,因?yàn)楸容^容易出問題(臟數(shù)據(jù)),而且也保證不了同步。?
5:那到底如何解決這樣的問題??
第一種:采用同步synchronized解決,這樣雖然解決了問題,但是也降低了系統(tǒng)的性能。?
第二種:采用原子性數(shù)據(jù)Atomic變量,這是從JDK1.5開始才存在的針對(duì)原子性的解決方案,這種方案也是目前比較好的解決方案了。?
6:Atomic的實(shí)現(xiàn)基本原理??
首先Atomic中的變量是申明為了volatile變量的,這樣就保證的變量的存儲(chǔ)和讀取是一致的,都是來自同一個(gè)內(nèi)存塊,然后Atomic提供了getAndIncrement方法,該方法對(duì)變量的++操作進(jìn)行了封裝,并提供了compareAndSet方法,來完成對(duì)單個(gè)變量的加鎖和解鎖操作,方法中用到了一個(gè)UnSafe的對(duì)象,現(xiàn)在還不知道這個(gè)UnSafe的工作原理(似乎沒有公開源代碼)。Atomic雖然解決了同步的問題,但是性能上面還是會(huì)有所損失,不過影響不大,網(wǎng)上有針對(duì)這方面的測試,大概50million的操作對(duì)比是250ms : 850ms,對(duì)于大部分的高性能應(yīng)用,應(yīng)該還是夠的了。?

Java代碼??
  • package?qflag.ucstar.test.thread;??
  • ??
  • import?java.util.concurrent.atomic.AtomicInteger;??
  • ??
  • /**?
  • ?*?測試原子性的同步?
  • ?*?@author?polarbear?2009-3-14?
  • ?*?
  • ?*/??
  • public?class?TestAtomic?{??
  • ??????
  • ????public?static?AtomicInteger?astom_i?=?new?AtomicInteger();??
  • ??????
  • ????public?static?volatile?Integer?v_integer_i?=?0;??
  • ??????
  • ????public?static?volatile?int?v_i?=?0;??
  • ??????
  • ????public?static?Integer?integer_i?=?0;??
  • ??????
  • ????public?static?int?i?=?0;??
  • ??????
  • ????public?static?int?endThread?=?0;??
  • ??????
  • ????public?static?void?main(String[]?args)?{??
  • ????????new?TestAtomic().testAtomic();??
  • ????}??
  • ??????
  • ????public?void?testAtomic()?{??
  • ??????????
  • ????????for(int?i=0;?i<100;?i++)?{??
  • ????????????new?Thread(new?IntegerTestThread()).start();??
  • ????????}??
  • ??????????
  • ????????try?{??
  • ????????????for(;;)?{??
  • ????????????????Thread.sleep(500);??
  • ????????????????if(TestAtomic.endThread?==?100)?{??
  • ????????????????????System.out.println(">>Execute?End:");??
  • ????????????????????System.out.println(">>Atomic:?\t"+TestAtomic.astom_i);??
  • ????????????????????System.out.println(">>VInteger:?\t"+TestAtomic.v_integer_i);??
  • ????????????????????System.out.println(">>Integer:?\t"+TestAtomic.integer_i);??
  • ????????????????????System.out.println(">>Source?i:?\t"+TestAtomic.i);??
  • ????????????????????System.out.println(">>Source?Vi:?\t"+TestAtomic.v_i);??
  • ????????????????????break;??
  • ????????????????}??
  • ????????????}??
  • ??????????????
  • ????????}?catch?(Exception?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ????}??
  • ??????
  • }??
  • class?IntegerTestThread?implements?Runnable?{??
  • ????public?void?run()?{??
  • ????????int?x?=?0;??
  • ????????while(x<1000)?{??
  • ????????????TestAtomic.astom_i.incrementAndGet();??
  • ????????????TestAtomic.v_integer_i++;??
  • ????????????TestAtomic.integer_i++;??
  • ????????????TestAtomic.i++;??
  • ????????????TestAtomic.v_i++;??
  • ????????????x++;??
  • ????????}??
  • ????????++TestAtomic.endThread;??
  • ????}??
  • } ?
  • 總結(jié)

    以上是生活随笔為你收集整理的java 原子锁的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。