Java練級(jí)打怪路----synchronized對(duì)比cas

前言

這篇文章的營(yíng)養(yǎng)非常有限,只是一個(gè)夜黑風(fēng)高的晚上,突發(fā)奇想,如果我要統(tǒng)計(jì)一個(gè)網(wǎng)站的PV,程序應(yīng)該怎么寫(xiě)呢?

一種挫逼的寫(xiě)法


這是一種無(wú)鎖的寫(xiě)法,很明顯,這個(gè)東西是線程不安全的。我們使用12個(gè)線程,每個(gè)線程執(zhí)行 108次方add的操作,發(fā)現(xiàn)最終的結(jié)果并沒(méi)有得到期望的1.2*109次方。


上面一個(gè)是總數(shù),下面一個(gè)是所消耗的時(shí)間。

synchronized VS cas

很明顯,我們需要一個(gè)鎖來(lái)干這個(gè)事情。

synchronized

synchronized關(guān)鍵字,是Java中一個(gè)同步鎖,主要有一下幾種用法:

  • 修飾一個(gè)代碼塊,被修飾的代碼塊稱為同步語(yǔ)句塊,其作用的范圍是大括號(hào){}括起來(lái)的代碼
  • 修飾一個(gè)方法,被修飾的方法稱為同步方法,其作用的范圍是整個(gè)方法
  • 修飾一個(gè)靜態(tài)的方法,其作用的范圍是整個(gè)靜態(tài)方法。

cas

compareAndSet,如果之前了解過(guò)C語(yǔ)言或者操作系統(tǒng),相信對(duì)cas不會(huì)太陌生,這是一個(gè)原子方法。Java中我們可以使用sun.misc.Unsafe#compareAndSwapLong這個(gè)方法。


對(duì)比

  • 測(cè)試環(huán)境:
  • 測(cè)試條件:
    每個(gè)線程執(zhí)行1千萬(wàn)次add 1操作
  • 測(cè)試結(jié)果:(4次取平均值)
線程數(shù) synchronized耗時(shí)(ms) cas耗時(shí)(ms) 方法三(ms)
1 296 142 92
4 2749 2611 999
8 5797 4845 1851
16 11223 10192 3702
32 14949 20009 7779
64 31415 39974 13784

發(fā)現(xiàn)

  • synchronized好快
    我們發(fā)現(xiàn)synchronized關(guān)鍵一開(kāi)始落后于cas,但是在后期卻完成反超。synchronized其實(shí)在JDK1.5進(jìn)行一波更新。速度大大的提升。
    后面我們?cè)倮^續(xù)深入將jdk對(duì)synchronized的優(yōu)化。
    cas在競(jìng)爭(zhēng)激烈的時(shí)候速度反而下降。不難想象反復(fù)的失敗重試。
  • CPU資源問(wèn)題
    我們發(fā)現(xiàn)了一個(gè)事情,synchronized執(zhí)行的過(guò)程中,CPU的資源一直上不去,這個(gè)也不難想到原因,因?yàn)槠渌€程一直競(jìng)爭(zhēng)不到鎖,一直處于阻塞的狀態(tài)。



    cas模型的CPU基本打滿。


  • cas的優(yōu)化
    jdk為我們提供了一個(gè)類(lèi)java.util.concurrent.atomic.AtomicLong,效果可以顯著提高。方法三我就是用這個(gè)測(cè)出來(lái)的。雖然方法二的實(shí)現(xiàn)跟方法三的一模一樣,我最后都直接copy代碼出來(lái)了,但仍然達(dá)不到該效率,估計(jì)是有jvm級(jí)別的優(yōu)化。
    當(dāng)然我們可以模擬jvm對(duì)synchronized的優(yōu)化,簡(jiǎn)單的說(shuō),jvm的moniter會(huì)根據(jù)競(jìng)爭(zhēng)的情況而調(diào)整synchronize的鎖,我們按照這一思路,如果cas交換次數(shù)失敗到一定的次數(shù),就阻塞這個(gè)線程。



    增加了這個(gè)條件之后耗時(shí)大概減少了40%,CPU的使用降低70%(32線程/64線程條件下),當(dāng)然這個(gè)1000是我胡亂搞出來(lái)的一個(gè)值,但線程數(shù)提升上去后仍然比synchronized慢。

  • synchronized是個(gè)好東西
    synchronized是一個(gè)非常穩(wěn)定的東西,雖然效率不一定是最佳的。但確實(shí)非常好用,下面再來(lái)認(rèn)真研究研究。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Java8張圖 11、字符串不變性 12、equals()方法、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,887評(píng)論 0 11
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,767評(píng)論 11 349
  • 一、多線程 說(shuō)明下線程的狀態(tài) java中的線程一共有 5 種狀態(tài)。 NEW:這種情況指的是,通過(guò) New 關(guān)鍵字創(chuàng)...
    Java旅行者閱讀 4,849評(píng)論 0 44
  • 夢(mèng)里自己是匠人實(shí)則是個(gè)犟人腦袋快要生病時(shí)認(rèn)真聽(tīng)聽(tīng)好人勸活著就不會(huì)倦熱烘烘的床細(xì)菌死光光 ???
    1024個(gè)比利閱讀 202評(píng)論 1 1
  • 那天很難得和她一起出去玩,一路上大伙開(kāi)開(kāi)心心聊著各種話題,風(fēng)景很美,但不及她在我身邊,風(fēng)景我啥時(shí)候來(lái)都在,可...
    小迅閱讀 188評(píng)論 0 0

友情鏈接更多精彩內(nèi)容