成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

勿對(duì)不可變對(duì)象做同步/加鎖

wangjuntytl / 416人閱讀

摘要:分析從面向?qū)ο缶幊虂砜矗i狀態(tài)不應(yīng)視為不可變對(duì)象的一部分,如果對(duì)它做同步,就是把鎖狀態(tài)視為它的一部分了,破壞了該對(duì)象的設(shè)計(jì)抽象。從并發(fā)編程來看,不可變的對(duì)象被設(shè)計(jì)為允許多線程自由共享,不引起競爭。

另載于 http://www.qingjingjie.com/blogs/10

概念

不可變對(duì)象(Immutable Object),就是狀態(tài)始終不會(huì)改變的對(duì)象,例如值對(duì)象(Value Object),無狀態(tài)的服務(wù)對(duì)象(Stateless Service Object)。

Java和Scala都是JVM語言,都經(jīng)常用synchronized來做同步。本文以Java為例,Scala同理。

先重溫一下synchronized的知識(shí):指定了一個(gè)同步范圍,進(jìn)出范圍刷新變量,并阻止其他線程進(jìn)入該范圍。synchronized method的范圍是this,synchronized static method的范圍是class,也可顯式指定一個(gè)對(duì)象作為范圍。

synchronized(object) {
 ...
}

同步范圍是作用于對(duì)象的,任何對(duì)象都含有一個(gè)隱藏的鎖狀態(tài),JVM把它置為鎖態(tài),就加上了當(dāng)前線程獨(dú)占的鎖。

分析

從面向?qū)ο缶幊虂砜?,鎖狀態(tài)不應(yīng)視為不可變對(duì)象的一部分,如果對(duì)它做同步,就是把鎖狀態(tài)視為它的一部分了,破壞了該對(duì)象的設(shè)計(jì)抽象。

從并發(fā)編程來看,不可變的對(duì)象被設(shè)計(jì)為允許多線程自由共享,不引起競爭。然而如果對(duì)它做同步,就會(huì)引起多線程競爭,違反了設(shè)計(jì)目的。

一般沒人會(huì)對(duì)值對(duì)象做同步,但可能有人會(huì)誤對(duì)無狀態(tài)的服務(wù)對(duì)象做同步。(牛人也可能有失誤)

我們來看個(gè)反面例子:

// UserService is singleton
public class UserService {
  // 修改數(shù)據(jù)庫中的用戶信息
  public synchronized User changeName(Long id, String name) {
    User user = UserRepo.get(id);
    user.setName(name);
    UserRepo.merge(user);
    return user;
  }
}

通過數(shù)據(jù)庫的事務(wù)隔離,能保證user從取出來到存回去之間不被別的線程修改。

但是NoSQL沒有事務(wù),怎么辦?NoSQL用戶可能會(huì)用synchronized,這就使得changeName同時(shí)只能被一個(gè)線程調(diào),網(wǎng)站扛不住并發(fā)。

考慮到不同用戶的數(shù)據(jù)可以同時(shí)修改,可以給每個(gè)用戶多帶帶上鎖,以提高并發(fā)度:

// UserService is singleton
public class UserService {
  private Map userLocks = new ConcurrentHashMap<>();

  // 修改數(shù)據(jù)庫中的用戶信息
  public synchronized User changeName(Long id, String name) {
    // 獲取鎖
    Object lock = new Object();
    Object prevLock = userLocks.putIfAbsent(id, lock);
    if (prevLock != null) {
      lock = prevLock;
    }
    
    synchronized (lock) {
      try {
        User user = UserRepo.get(id);
        user.setName(name);
        UserRepo.merge(user);
        return user;
      } finally {
        // 防止太多空閑的鎖占用內(nèi)存
        userLocks.remove(id);
      }
    }
  }
}

玩玩而已,這么復(fù)雜的代碼,我覺得產(chǎn)品里還是不寫為好。

況且,在集群環(huán)境中,這種單機(jī)同步是沒用的。

附:JDK也有類似的并發(fā)優(yōu)化,見我的舊文 http://www.cnblogs.com/sorra/p/3653951.html

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/64363.html

相關(guān)文章

  • 40道阿里巴巴JAVA研發(fā)崗多線程面試題詳解,你能答出多少

    摘要:但是單核我們還是要應(yīng)用多線程,就是為了防止阻塞。多線程可以防止這個(gè)問題,多條線程同時(shí)運(yùn)行,哪怕一條線程的代碼執(zhí)行讀取數(shù)據(jù)阻塞,也不會(huì)影響其它任務(wù)的執(zhí)行。 1、多線程有什么用?一個(gè)可能在很多人看來很扯淡的一個(gè)問題:我會(huì)用多線程就好了,還管它有什么用?在我看來,這個(gè)回答更扯淡。所謂知其然知其所以然,會(huì)用只是知其然,為什么用才是知其所以然,只有達(dá)到知其然知其所以然的程度才可以說是把一個(gè)知識(shí)點(diǎn)...

    lpjustdoit 評(píng)論0 收藏0
  • 多線程基礎(chǔ)必要知識(shí)點(diǎn)!看了學(xué)習(xí)多線程事半功倍

    摘要:是需要我們?nèi)ヌ幚砗芏嗍虑?,為了防止多線程給我們帶來的安全和性能的問題下面就來簡單總結(jié)一下我們需要哪些知識(shí)點(diǎn)來解決多線程遇到的問題。 前言 不小心就鴿了幾天沒有更新了,這個(gè)星期回家咯。在學(xué)校的日子要努力一點(diǎn)才行! 只有光頭才能變強(qiáng) 回顧前面: 多線程三分鐘就可以入個(gè)門了! Thread源碼剖析 本文章的知識(shí)主要參考《Java并發(fā)編程實(shí)戰(zhàn)》這本書的前4章,這本書的前4章都是講解并發(fā)的基...

    YPHP 評(píng)論0 收藏0
  • Java 虛擬機(jī)總結(jié)給面試的你(下)

    摘要:本篇博客主要針對(duì)虛擬機(jī)的晚期編譯優(yōu)化,內(nèi)存模型與線程,線程安全與鎖優(yōu)化進(jìn)行總結(jié),其余部分總結(jié)請(qǐng)點(diǎn)擊虛擬總結(jié)上篇,虛擬機(jī)總結(jié)中篇。 本篇博客主要針對(duì)Java虛擬機(jī)的晚期編譯優(yōu)化,Java內(nèi)存模型與線程,線程安全與鎖優(yōu)化進(jìn)行總結(jié),其余部分總結(jié)請(qǐng)點(diǎn)擊Java虛擬總結(jié)上篇 ,Java虛擬機(jī)總結(jié)中篇。 一.晚期運(yùn)行期優(yōu)化 即時(shí)編譯器JIT 即時(shí)編譯器JIT的作用就是熱點(diǎn)代碼轉(zhuǎn)換為平臺(tái)相關(guān)的機(jī)器碼...

    amc 評(píng)論0 收藏0
  • 「Java并發(fā)編程實(shí)戰(zhàn)」之對(duì)象的共享

    摘要:當(dāng)某個(gè)不應(yīng)該發(fā)布的對(duì)象被發(fā)布時(shí),這種情況被稱為逸出。線程安全共享線程安全的對(duì)象在其內(nèi)部實(shí)現(xiàn)同步,因此多線程可以通過對(duì)象的公有接口來進(jìn)行訪問而不需要進(jìn)一步的同步。 前言   本系列博客是對(duì)《Java并發(fā)編程實(shí)戰(zhàn)》的一點(diǎn)總結(jié),本篇主要講解以下幾個(gè)內(nèi)容,內(nèi)容會(huì)比較枯燥??赡艽蠹铱礃?biāo)題不能能直觀的感受出到底什么意思,這就是專業(yè)術(shù)語,哈哈,解釋下,術(shù)語(terminology)是在特定學(xué)科領(lǐng)域用...

    phodal 評(píng)論0 收藏0
  • 線程安全

    摘要:不可變?cè)谥?,不可變的?duì)象一定是線程安全的。在里標(biāo)注自己是線程安全的類,大多都不是絕對(duì)線程安全,比如某些情況下類在調(diào)用端也需要額外的同步措施。無同步方案要保證線程安全,不一定就得需要數(shù)據(jù)的同步,兩者沒有因果關(guān)系。 在之前學(xué)習(xí)編程的時(shí)候,有一個(gè)概念根深蒂固,即程序=算法+數(shù)據(jù)結(jié)構(gòu)。數(shù)據(jù)代表問題空間中的客體,代碼就用來處理這些數(shù)據(jù),這種思維是站在計(jì)算機(jī)的角度去抽象問題和解決問題,稱之為面向過...

    fuyi501 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<