摘要:分析從面向?qū)ο缶幊虂砜?,鎖狀態(tài)不應視為不可變對象的一部分,如果對它做同步,就是把鎖狀態(tài)視為它的一部分了,破壞了該對象的設計抽象。從并發(fā)編程來看,不可變的對象被設計為允許多線程自由共享,不引起競爭。
另載于 http://www.qingjingjie.com/blogs/10
概念不可變對象(Immutable Object),就是狀態(tài)始終不會改變的對象,例如值對象(Value Object),無狀態(tài)的服務對象(Stateless Service Object)。
Java和Scala都是JVM語言,都經(jīng)常用synchronized來做同步。本文以Java為例,Scala同理。
先重溫一下synchronized的知識:指定了一個同步范圍,進出范圍刷新變量,并阻止其他線程進入該范圍。synchronized method的范圍是this,synchronized static method的范圍是class,也可顯式指定一個對象作為范圍。
synchronized(object) { ... }
同步范圍是作用于對象的,任何對象都含有一個隱藏的鎖狀態(tài),JVM把它置為鎖態(tài),就加上了當前線程獨占的鎖。
分析從面向?qū)ο缶幊虂砜?,鎖狀態(tài)不應視為不可變對象的一部分,如果對它做同步,就是把鎖狀態(tài)視為它的一部分了,破壞了該對象的設計抽象。
從并發(fā)編程來看,不可變的對象被設計為允許多線程自由共享,不引起競爭。然而如果對它做同步,就會引起多線程競爭,違反了設計目的。
一般沒人會對值對象做同步,但可能有人會誤對無狀態(tài)的服務對象做同步。(牛人也可能有失誤)
我們來看個反面例子:
// 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ù)庫的事務隔離,能保證user從取出來到存回去之間不被別的線程修改。
但是NoSQL沒有事務,怎么辦?NoSQL用戶可能會用synchronized,這就使得changeName同時只能被一個線程調(diào),網(wǎng)站扛不住并發(fā)。
考慮到不同用戶的數(shù)據(jù)可以同時修改,可以給每個用戶多帶帶上鎖,以提高并發(fā)度:
// UserService is singleton public class UserService { private MapuserLocks = 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); } } } }
玩玩而已,這么復雜的代碼,我覺得產(chǎn)品里還是不寫為好。
況且,在集群環(huán)境中,這種單機同步是沒用的。
附:JDK也有類似的并發(fā)優(yōu)化,見我的舊文 http://www.cnblogs.com/sorra/p/3653951.html
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/64363.html
摘要:但是單核我們還是要應用多線程,就是為了防止阻塞。多線程可以防止這個問題,多條線程同時運行,哪怕一條線程的代碼執(zhí)行讀取數(shù)據(jù)阻塞,也不會影響其它任務的執(zhí)行。 1、多線程有什么用?一個可能在很多人看來很扯淡的一個問題:我會用多線程就好了,還管它有什么用?在我看來,這個回答更扯淡。所謂知其然知其所以然,會用只是知其然,為什么用才是知其所以然,只有達到知其然知其所以然的程度才可以說是把一個知識點...
摘要:是需要我們?nèi)ヌ幚砗芏嗍虑?,為了防止多線程給我們帶來的安全和性能的問題下面就來簡單總結(jié)一下我們需要哪些知識點來解決多線程遇到的問題。 前言 不小心就鴿了幾天沒有更新了,這個星期回家咯。在學校的日子要努力一點才行! 只有光頭才能變強 回顧前面: 多線程三分鐘就可以入個門了! Thread源碼剖析 本文章的知識主要參考《Java并發(fā)編程實戰(zhàn)》這本書的前4章,這本書的前4章都是講解并發(fā)的基...
摘要:本篇博客主要針對虛擬機的晚期編譯優(yōu)化,內(nèi)存模型與線程,線程安全與鎖優(yōu)化進行總結(jié),其余部分總結(jié)請點擊虛擬總結(jié)上篇,虛擬機總結(jié)中篇。 本篇博客主要針對Java虛擬機的晚期編譯優(yōu)化,Java內(nèi)存模型與線程,線程安全與鎖優(yōu)化進行總結(jié),其余部分總結(jié)請點擊Java虛擬總結(jié)上篇 ,Java虛擬機總結(jié)中篇。 一.晚期運行期優(yōu)化 即時編譯器JIT 即時編譯器JIT的作用就是熱點代碼轉(zhuǎn)換為平臺相關的機器碼...
摘要:當某個不應該發(fā)布的對象被發(fā)布時,這種情況被稱為逸出。線程安全共享線程安全的對象在其內(nèi)部實現(xiàn)同步,因此多線程可以通過對象的公有接口來進行訪問而不需要進一步的同步。 前言 本系列博客是對《Java并發(fā)編程實戰(zhàn)》的一點總結(jié),本篇主要講解以下幾個內(nèi)容,內(nèi)容會比較枯燥??赡艽蠹铱礃祟}不能能直觀的感受出到底什么意思,這就是專業(yè)術(shù)語,哈哈,解釋下,術(shù)語(terminology)是在特定學科領域用...
閱讀 664·2021-11-23 09:51
閱讀 3305·2021-10-11 10:58
閱讀 15468·2021-09-29 09:47
閱讀 3563·2021-09-01 11:42
閱讀 1293·2019-08-29 16:43
閱讀 1839·2019-08-29 15:37
閱讀 2112·2019-08-29 12:56
閱讀 1729·2019-08-28 18:21