竟然將線程安全講的如此清新脫俗,談?wù)勀銓?duì)線程安全性的理解!
1.官方定義
線程安全通常是相對(duì)于多線程或者并發(fā)的情況下而言的。如果是單線程操作的話,就無所謂線程安全了。
簡單來說,就是在多個(gè)線程環(huán)境下,訪問同一個(gè)對(duì)象時(shí),如果不用考慮這些線程在運(yùn)行時(shí)環(huán)境下的調(diào)度和交替執(zhí)行,在不做任何干預(yù)的強(qiáng)可選,調(diào)用這個(gè)對(duì)象的行為都可以獲得預(yù)期的結(jié)果,那么這個(gè)對(duì)象就是線程安全的。
看完這段,是不是還是很難理解?下面,我來分享一下看我是如何理解的。
2.Tom的理解
我認(rèn)為,在多線程環(huán)境下保證線程安全,無非就是保證對(duì)對(duì)象訪問的原子性、有序性和多個(gè)線程之間的可見性。
原子性呢,說的是當(dāng)一個(gè)線程執(zhí)行一系列程序指令操作的時(shí)候,它應(yīng)該是不可中斷的,因?yàn)橐坏┏霈F(xiàn)中斷,站在多線程的視角來看,這一系列的程序指令會(huì)出現(xiàn)前后執(zhí)行結(jié)果不一致的問題。
這個(gè)和數(shù)據(jù)庫里面的原子性是一樣的,簡單來說就是一段程序只能由一個(gè)線程完整的執(zhí)行完成,而不能存在多個(gè)線程干擾。CPU的上下文切換 , 是導(dǎo)致出現(xiàn)多線程原子性問題的核心原因 , 而JDK面也提供了synchronized 關(guān)鍵字來解決原子性問題。
然后,就是可見性,相當(dāng)于在多線程環(huán)境下,可能會(huì)存在讀和寫是發(fā)生在不同的線程里面,有可能出現(xiàn)某個(gè)線程對(duì)共享變量的修改,對(duì)其他線程不是實(shí)時(shí)可見的。導(dǎo)致可見性問題的原因有很多,比如 CPU的高速緩存、CPU的指令重排、編譯器的指令重排等因素。
最后,就是有序性,指的是程序編寫的指令順序和最終 CPU 運(yùn)行的指令順序可能出現(xiàn)不一致的現(xiàn)象,這種現(xiàn)象也可以稱為指令重排序,所以有序性也會(huì)導(dǎo)致可見性問題。可見性和有序性可以通過JDK提供的volatile 關(guān)鍵字來解決。
我認(rèn)為,導(dǎo)致有序性、原子性、可見性問題的本質(zhì),是計(jì)算機(jī)設(shè)計(jì)的時(shí)候,為了最大化提升 CPU 利用率導(dǎo)致的。比如CPU設(shè)計(jì)了三級(jí)緩存、設(shè)計(jì)了 StoreBuffer、設(shè)計(jì)了緩存行這種預(yù)讀機(jī)制、在操作系統(tǒng)里面,設(shè)計(jì)了線程模型、在編譯器里面,設(shè)計(jì)了編譯器的深度優(yōu)化機(jī)制等等。
我們都在說,面試造火箭,工作擰螺絲。對(duì)于企業(yè)來說,如果選擇一個(gè)對(duì)計(jì)算機(jī)底層原理了解更透徹的程序員,不用擔(dān)心他濫用線程導(dǎo)致一些不可預(yù)測(cè)的安全問題。其實(shí)也是在降低用人成本。
最后,我把之前分享的視頻全部整理成了文字,想獲取的小伙伴可以從我的個(gè)人煮葉簡介中找到,希望能夠以此來提高各位粉絲的通過率。
我是被編程耽誤的文藝Tom,如果我的分享對(duì)你有幫助,請(qǐng)動(dòng)動(dòng)手指一鍵三連分享給更多的人。關(guān)注我,面試不再難!