国内Java面试总是问StringBuffer,StringBuilder区别是啥?档次为什么这么低?
這是一個知乎上面很火的問題(https://www.zhihu.com/question/50211894 ),下面是我關(guān)于這個問題的回答,截止今天,這個答案收獲了500+贊和70+評論。
原答案
這個問題只是開個場,熱個身而已啊。
StringBuffer,StringBuilder區(qū)別是啥?
什么是線程安全?
如何保證線程安全?
什么是鎖?死鎖?
synchronized的實現(xiàn)原理是什么?
有了synchronized,還要volatile干什么?
synchronized的鎖優(yōu)化是怎么回事?(鎖粗化?鎖消除?自旋鎖?偏向鎖?輕量級鎖?)
知道JMM嗎?(原子性?可見性?有序性?)
Java并發(fā)包了解嗎?
那什么是fail-fast?什么是fail-safe?
什么是CopyOnWrite?
那AQS呢?那CAS呢?
CAS都知道,那樂觀鎖一定知道了?
樂觀鎖悲觀鎖區(qū)別是什么?
數(shù)據(jù)庫如何實現(xiàn)悲觀鎖和樂觀鎖?
數(shù)據(jù)庫鎖有了解么?行級鎖?表級鎖?共享鎖?排他鎖?gap鎖?next-key lock?
數(shù)據(jù)庫鎖和隔離級別有什么關(guān)系?
數(shù)據(jù)庫鎖和索引有什么關(guān)系?
什么是聚簇索引?非聚簇索引?最左前綴是什么?B+樹索引?聯(lián)合索引?回表?
分布式鎖有了解嗎?
Redis怎么實現(xiàn)分布式鎖?
為什么要用Redis?
Redis和memcache區(qū)別是什么?
Zookeeper怎么實現(xiàn)分布式鎖?
什么是Zookeeper?
什么是CAP?
什么是BASE?和CAP什么區(qū)別?
CAP怎么推導(dǎo)?如何取舍?
分布式系統(tǒng)怎么保證數(shù)據(jù)一致性?
啥是分布式事務(wù)?分布式事務(wù)方案?
那么,最后了,來手寫一個線程安全的單例吧?
不用synchronized和lock能實現(xiàn)線程安全的單例嗎?
這你都能答上?那好吧,你給我解釋下什么是Paxos算法吧?
卒~!
部分答案
針對以上的問題,我給一些答案,希望大家都能有所收獲。這些答案也都是從我的博客中歷史文章總結(jié)出來的。
部分問題簡單幾句可以說的清楚的,我就直接貼答案了,比較復(fù)雜的,我貼個傳送門。
但是,以下答案可能并不完整,比如一些比較類的,我可能只說重點或者和這個知識體系有關(guān)的關(guān)鍵點,所以希望讀者可以根據(jù)下面的問題,完善每一個問題的答案。
StringBuffer,StringBuilder區(qū)別是啥?
StringBuffer是線程安全的,而StringBuilder是非線程安全的。
什么是線程安全?
線程安全是編程中的術(shù)語,指某個函數(shù)、函數(shù)庫在并發(fā)環(huán)境中被調(diào)用時,能夠正確地處理多個線程之間的共享變量,使程序功能正確完成。即在多線程場景下,不發(fā)生有序性、原子性以及可見性問題。
如何保證線程安全?
Java中主要通過加鎖來實現(xiàn)線程安全。通常使用synchronized和Lock
什么是鎖?死鎖?
死鎖是指兩個或兩個以上的進程在執(zhí)行過程中,由于競爭資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象,若無外力作用,它們都將無法推進下去。此時稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖,這些永遠在互相等待的進程稱為死鎖進程。
死鎖的發(fā)生必須具備以下四個必要條件:互斥條件、請求和保持條件、不剝奪條件、環(huán)路等待條件
死鎖的解決辦法就是破壞以上四種必備條件中的一個或者多個。
synchronized的實現(xiàn)原理是什么?
深入理解多線程(一)——Synchronized的實現(xiàn)原理 深入理解多線程(四)—— Moniter的實現(xiàn)原理 再有人問你synchronized是什么,就把這篇文章發(fā)給他
有了synchronized,還要volatile干什么?
volatile通常被比喻成”輕量級的synchronized“,volatile可以保證可見性和有序性,實現(xiàn)原理是通過內(nèi)存屏障實現(xiàn)的。
volatile有一個重要的作用,是synchronized不具備的,那就是禁止指令重排序。這一特點在雙重校驗鎖實現(xiàn)單例的時候有用到,雖然使用了synchronized關(guān)鍵字,但是如果不用volatile修飾單例對象,就會存在問題。
深入理解Java中的volatile關(guān)鍵字 再有人問你synchronized是什么,就把這篇文章發(fā)給他。
synchronized的鎖優(yōu)化是怎么回事?(鎖粗化?鎖消除?自旋鎖?偏向鎖?輕量級鎖?)
深入理解多線程(五)—— Java虛擬機的鎖優(yōu)化技術(shù)
知道JMM嗎?(原子性?可見性?有序性?)
Java內(nèi)存模型(Java Memory Model ,JMM)是一種符合內(nèi)存模型規(guī)范的,屏蔽了各種硬件和操作系統(tǒng)的訪問差異的,保證了Java程序在各種平臺下對內(nèi)存的訪問都能保證效果一致的機制及規(guī)范。
再有人問你Java內(nèi)存模型是什么,就把這篇文章發(fā)給他。
Java并發(fā)包了解嗎?
java.util.concurrent包(J.U.C)中包含的是java并發(fā)編程中有用的一些工具類,包括幾個部分:
1、locks部分:包含在java.util.concurrent.locks包中,提供顯式鎖(互斥鎖和速寫鎖)相關(guān)功能;
2、atomic部分:包含在java.util.concurrent.atomic包中,提供原子變量類相關(guān)的功能,是構(gòu)建非阻塞算法的基礎(chǔ);
3、executor部分:散落在java.util.concurrent包中,提供線程池相關(guān)的功能;
4、collections部分:散落在java.util.concurrent包中,提供并發(fā)容器相關(guān)功能;
5、tools部分:散落在java.util.concurrent包中,提供同步工具類,如信號量、閉鎖、柵欄等功能;
那什么是fail-fast?什么是fail-safe?
我們通常說的Java中的fail-fast機制,默認(rèn)指的是Java集合的一種錯誤檢測機制。當(dāng)多個線程對部分集合進行結(jié)構(gòu)上的改變的操作時,有可能會產(chǎn)生fail-fast機制,這個時候就會拋出ConcurrentModificationException。
ConcurrentModificationException,當(dāng)方法檢測到對象的并發(fā)修改,但不允許這種修改時就拋出該異常。
為了避免觸發(fā)fail-fast機制,導(dǎo)致異常,我們可以使用Java中提供的一些采用了fail-safe機制的集合類。
這樣的集合容器在遍歷時不是直接在集合內(nèi)容上訪問的,而是先復(fù)制原有集合內(nèi)容,在拷貝的集合上進行遍歷。
java.util.concurrent包下的容器都是fail-safe的,可以在多線程下并發(fā)使用,并發(fā)修改。同時也可以在foreach中進行add/remove 。
一不小心就踩坑的fail-fast是個什么鬼?
什么是CopyOnWrite?
Copy-On-Write簡稱COW,是一種用于程序設(shè)計中的優(yōu)化策略。其基本思路是,從一開始大家都在共享同一個內(nèi)容,當(dāng)某個人想要修改這個內(nèi)容的時候,才會真正把內(nèi)容Copy出去形成一個新的內(nèi)容然后再改,這是一種延時懶惰策略。
CopyOnWrite容器即寫時復(fù)制的容器。通俗的理解是當(dāng)我們往一個容器添加元素的時候,不直接往當(dāng)前容器添加,而是先將當(dāng)前容器進行Copy,復(fù)制出一個新的容器,然后新的容器里添加元素,添加完元素之后,再將原容器的引用指向新的容器。
一不小心就踩坑的fail-fast是個什么鬼?
那AQS呢?那CAS呢?
AQS(AbstractQueuedSynchronizer),即隊列同步器。它是構(gòu)建鎖或者其他同步組件的基礎(chǔ)框架(如ReentrantLock、ReentrantReadWriteLock、Semaphore等),JUC并發(fā)包的作者(Doug Lea)期望它能夠成為實現(xiàn)大部分同步需求的基礎(chǔ)。它是JUC并發(fā)包中的核心基礎(chǔ)組件。
CAS是項樂觀鎖技術(shù),當(dāng)多個線程嘗試使用CAS同時更新同一個變量時,只有其中一個線程能更新變量的值,而其它線程都失敗,失敗的線程并不會被掛起,而是被告知這次競爭中失敗,并可以再次嘗試。
CAS 操作包含三個操作數(shù) —— 內(nèi)存位置(V)、預(yù)期原值(A)和新值(B)。如果內(nèi)存位置的值與預(yù)期原值相匹配,那么處理器會自動將該位置值更新為新值。否則,處理器不做任何操作。無論哪種情況,它都會在 CAS 指令之前返回該位置的值。(在 CAS 的一些特殊情況下將僅返回 CAS 是否成功,而不提取當(dāng)前值。)CAS 有效地說明了“我認(rèn)為位置 V 應(yīng)該包含值 A;如果包含該值,則將 B 放到這個位置;否則,不要更改該位置,只告訴我這個位置現(xiàn)在的值即可?!边@其實和樂觀鎖的沖突檢查+數(shù)據(jù)更新的原理是一樣的。
樂觀鎖的一種實現(xiàn)方式——CAS
CAS都知道,那樂觀鎖一定知道了?
樂觀鎖( Optimistic Locking ) 相對悲觀鎖而言,樂觀鎖假設(shè)認(rèn)為數(shù)據(jù)一般情況下不會造成沖突,所以在數(shù)據(jù)進行提交更新的時候,才會正式對數(shù)據(jù)的沖突與否進行檢測,如果發(fā)現(xiàn)沖突了,則讓返回用戶錯誤的信息,讓用戶決定如何去做。
相對于悲觀鎖,在對數(shù)據(jù)庫進行處理的時候,樂觀鎖并不會使用數(shù)據(jù)庫提供的鎖機制。一般的實現(xiàn)樂觀鎖的方式就是記錄數(shù)據(jù)版本。
實現(xiàn)數(shù)據(jù)版本有兩種方式,第一種是使用版本號,第二種是使用時間戳。
深入理解樂觀鎖與悲觀鎖
樂觀鎖悲觀鎖區(qū)別是什么?
同上
數(shù)據(jù)庫如何實現(xiàn)悲觀鎖和樂觀鎖?
深入理解樂觀鎖與悲觀鎖
數(shù)據(jù)庫鎖有了解么?行級鎖?表級鎖?共享鎖?排他鎖?gap鎖?next-key lock?
MySQL中的行級鎖,表級鎖,頁級鎖
MySQL中的共享鎖與排他鎖
數(shù)據(jù)庫鎖和隔離級別有什么關(guān)系?
很多DBMS定義了多個不同的“事務(wù)隔離等級”來控制鎖的程度和并發(fā)能力。
ANSI/ISO SQL定義的標(biāo)準(zhǔn)隔離級別有四種,從高到底依次為:可序列化(Serializable)、可重復(fù)讀(Repeatable reads)、提交讀(Read committed)、未提交讀(Read uncommitted)。
深入分析事務(wù)的隔離級別
數(shù)據(jù)庫鎖和索引有什么關(guān)系?
在MySQL中,行級鎖并不是直接鎖記錄,而是鎖索引。索引分為主鍵索引和非主鍵索引兩種,如果一條sql語句操作了主鍵索引,MySQL就會鎖定這條主鍵索引;如果一條語句操作了非主鍵索引,MySQL會先鎖定該非主鍵索引,再鎖定相關(guān)的主鍵索引。
什么是聚簇索引?非聚簇索引?最左前綴是什么?B+樹索引?聯(lián)合索引?回表?
主鍵索引的葉子節(jié)點存的是整行數(shù)據(jù)。在InnoDB中,主鍵索引也被稱為聚簇索引(clustered index)
非主鍵索引的葉子節(jié)點的內(nèi)容是主鍵的值,在InnoDB中,非主鍵索引也被稱為非聚簇索引(secondary index)
當(dāng)我們創(chuàng)建一個聯(lián)合索引的時候,如(key1,key2,key3),相當(dāng)于創(chuàng)建了(key1)、(key1,key2)和(key1,key2,key3)三個索引,這就是最左匹配原則。
在 InnoDB 里,索引B+ Tree的葉子節(jié)點存儲了整行數(shù)據(jù)的是主鍵索引。而索引B+ Tree的葉子節(jié)點存儲了主鍵的值的是非主鍵索引。因為主鍵索引樹的葉子節(jié)點直接就是我們要查詢的整行數(shù)據(jù)了。而非主鍵索引的葉子節(jié)點是主鍵的值,查到主鍵的值以后,還需要再通過主鍵的值再進行一次查詢,這個過程叫做回表。
我以為我對Mysql索引很了解,直到我遇到了阿里的面試官
分布式鎖有了解嗎?
目前比較常用的有以下幾種方案:
基于數(shù)據(jù)庫實現(xiàn)分布式鎖 基于緩存(redis,memcached,tair)實現(xiàn)分布式鎖 基于Zookeeper實現(xiàn)分布式鎖
分布式鎖的幾種實現(xiàn)方式~
Redis怎么實現(xiàn)分布式鎖?
多個進程執(zhí)行以下Redis命令:
SETNX lock.foo
如果 SETNX 返回1,說明該進程獲得鎖,SETNX將鍵 lock.foo 的值設(shè)置為鎖的超時時間(當(dāng)前時間 + 鎖的有效時間)。 如果 SETNX 返回0,說明其他進程已經(jīng)獲得了鎖,進程不能進入臨界區(qū)。進程可以在一個循環(huán)中不斷地嘗試 SETNX 操作,以獲得鎖。
為什么要用Redis?
分布式緩存,提升性能
Redis和memcache區(qū)別是什么?
1、存儲方式:Memcache把數(shù)據(jù)全部存在內(nèi)存之中,斷電后會掛掉,數(shù)據(jù)不能超 過內(nèi)存大小。Redis支持?jǐn)?shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保存在磁盤中,重啟時可以再次加載進行使用。(RDB快照和AOF日志兩 種持久化方式)。
2、Redis支持?jǐn)?shù)據(jù)的備份,及master-slave模式的數(shù)據(jù)備份。
3、數(shù)據(jù)支持類型:Redis在數(shù)據(jù)支持上要比Memcache多得多。
4、使用底層模型不同:新版本的Redis直接自己構(gòu)建了VM機制,因為一般的系統(tǒng)調(diào)用系統(tǒng)函數(shù)的話,會浪費一定的時間去移動和請求。
Zookeeper怎么實現(xiàn)分布式鎖?
基于zookeeper臨時有序節(jié)點可以實現(xiàn)的分布式鎖。
大致思想即為:每個客戶端對某個方法加鎖時,在zookeeper上的與該方法對應(yīng)的指定節(jié)點的目錄下,生成一個唯一的瞬時有序節(jié)點。 判斷是否獲取鎖的方式很簡單,只需要判斷有序節(jié)點中序號最小的一個。 當(dāng)釋放鎖的時候,只需將這個瞬時節(jié)點刪除即可。同時,其可以避免服務(wù)宕機導(dǎo)致的鎖無法釋放,而產(chǎn)生的死鎖問題。
分布式鎖的幾種實現(xiàn)方式~
什么是Zookeeper?
Zookeeper是一個開放源碼的分布式服務(wù)協(xié)調(diào)組件,是Google Chubby的開源實現(xiàn)。是一個高性能的分布式數(shù)據(jù)一致性解決方案。他將那些復(fù)雜的、容易出錯的分布式一致性服務(wù)封裝起來,構(gòu)成一個高效可靠的原語集,并提供一系列簡單易用的接口給用戶使用。
Zookeeper介紹(二)——Zookeeper概述
什么是CAP?
CAP理論:一個分布式系統(tǒng)最多只能同時滿足一致性(Consistency)、可用性(Availability)和分區(qū)容錯性(Partition tolerance)這三項中的兩項。
分布式系統(tǒng)的CAP理論
什么是BASE?和CAP什么區(qū)別?
BASE理論是對CAP理論的延伸,核心思想是即使無法做到強一致性(Strong Consistency,CAP的一致性就是強一致性),但應(yīng)用可以采用適合的方式達到最終一致性(Eventual Consitency)。
BASE是指基本可用(Basically Available)、軟狀態(tài)( Soft State)、最終一致性( Eventual Consistency)。
分布式系統(tǒng)的BASE理論
CAP怎么推導(dǎo)?如何取舍?
對于涉及到錢財這樣不能有一絲讓步的場景,C必須保證。網(wǎng)絡(luò)發(fā)生故障寧可停止服務(wù),這是保證CP,舍棄A。比如前幾年支付寶光纜被挖斷的事件,在網(wǎng)絡(luò)出現(xiàn)故障的時候,支付寶就在可用性和數(shù)據(jù)一致性之間選擇了數(shù)據(jù)一致性,用戶感受到的是支付寶系統(tǒng)長時間宕機,但是其實背后是無數(shù)的工程師在恢復(fù)數(shù)據(jù),保證數(shù)數(shù)據(jù)的一致性。
對于其他場景,比較普遍的做法是選擇可用性和分區(qū)容錯性,舍棄強一致性,退而求其次使用最終一致性來保證數(shù)據(jù)的安全。
分布式系統(tǒng)的CAP理論
分布式系統(tǒng)怎么保證數(shù)據(jù)一致性?
分布式事務(wù)
啥是分布式事務(wù)?分布式事務(wù)方案?
分布式事務(wù)是指會涉及到操作多個數(shù)據(jù)庫的事務(wù)。其實就是將對同一庫事務(wù)的概念擴大到了對多個庫的事務(wù)。目的是為了保證分布式系統(tǒng)中的數(shù)據(jù)一致性。分布式事務(wù)處理的關(guān)鍵是必須有一種方法可以知道事務(wù)在任何地方所做的所有動作,提交或回滾事務(wù)的決定必須產(chǎn)生統(tǒng)一的結(jié)果(全部提交或全部回滾)
關(guān)于分布式事務(wù)、兩階段提交協(xié)議、三階提交協(xié)議
分布式事務(wù)解決方案——柔性事務(wù)與服務(wù)模式
那么,最后了,來手寫一個線程安全的單例吧?
單例模式的七種寫法
為什么我墻裂建議大家使用枚舉來實現(xiàn)單例
不用synchronized和lock能實現(xiàn)線程安全的單例嗎?
借助CAS(AtomicReference)實現(xiàn)單例模式:
public class Singleton {private static final AtomicReference<Singleton> INSTANCE = new AtomicReference<Singleton>(); private Singleton() {}public static Singleton getInstance() {for (;;) {Singleton singleton = INSTANCE.get();if (null != singleton) {return singleton;}singleton = new Singleton();if (INSTANCE.compareAndSet(null, singleton)) {return singleton;}}} }用CAS的好處在于不需要使用傳統(tǒng)的鎖機制來保證線程安全,CAS是一種基于忙等待的算法,依賴底層硬件的實現(xiàn),相對于鎖它沒有線程切換和阻塞的額外消耗,可以支持較大的并行度。 CAS的一個重要缺點在于如果忙等待一直執(zhí)行不成功(一直在死循環(huán)中),會對CPU造成較大的執(zhí)行開銷。
不使用synchronized和lock,如何實現(xiàn)一個線程安全的單例?
不使用synchronized和lock,如何實現(xiàn)一個線程安全的單例?(二)
這你都能答上?那好吧,你給我解釋下什么是Paxos算法吧?
Paxos一種基于消息傳遞且具有高度容錯特性的一致性算法。Paxos算法號稱是最難理解的算法!!!
總結(jié)
面試,其實是一個循序漸進的過程,面試官不可能上來就讓一個面試者手?jǐn)]paxos算法,總要先拋出一個比較簡單的問題,然后根據(jù)面試者回答的情況,逐漸的展開和深入。
另外 ,以上問題的"推倒"過程,其實就是一個完整的知識體系,很多人在我的公眾號后臺以及微信好友問我到底什么是知識體系,如何構(gòu)建自己的知識體系。
這個問題并沒有什么標(biāo)準(zhǔn)答案,同樣一個知識點,不斷的展開,把多個知識點互相連接,這就是一個知識體系。每個人的知識體系都不相同。但是構(gòu)建過程都是一樣的,那就是圖論中的"深度優(yōu)先搜索"和"廣度優(yōu)先搜索",就看哪種比較適合你了。
總結(jié)
以上是生活随笔為你收集整理的国内Java面试总是问StringBuffer,StringBuilder区别是啥?档次为什么这么低?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STL之set集合容器
- 下一篇: NYOJ 914 Yougth的最大化(