靜態(tài)方法和普通方法同時(shí)加上synchronized有什么區(qū)別?
A. 無(wú)論synchronized關(guān)鍵字加在方法上還是對(duì)象上,如果它作用的對(duì)象是非靜態(tài)的,則它取得的鎖是對(duì)象;如果synchronized作用的對(duì)象是一個(gè)靜態(tài)方法或一個(gè)類,則它取得的鎖是對(duì)類,該類所有的對(duì)象同一把鎖。
B. 每個(gè)對(duì)象只有一個(gè)鎖(lock)與之相關(guān)聯(lián),誰(shuí)拿到這個(gè)鎖誰(shuí)就可以運(yùn)行它所控制的那段代碼。
C. 實(shí)現(xiàn)同步是要很大的系統(tǒng)開銷作為代價(jià)的,甚至可能造成死鎖,所以盡量避免無(wú)謂的同步控制。
線程池的類型,固定大小的線程池內(nèi)部是如何實(shí)現(xiàn)的,等待隊(duì)列是用了哪一個(gè)隊(duì)列實(shí)現(xiàn)
線程池的底層實(shí)現(xiàn)
談一談對(duì)volatile理解,這個(gè)問(wèn)題很常見,答出要點(diǎn): 可見性、防止指令重排即可
多線程:創(chuàng)建多線程的三種方法及其區(qū)別,線程同步方法,synchronize和ReentrantLock的區(qū)別,synchronize的用法(修飾類,方法,代碼塊等)以及使用對(duì)象是什么,sleep和wait的區(qū)別
指令重排的含義
volatile 原理 使用 指令重排 內(nèi)存屏障 保證內(nèi)存可見性
volatile實(shí)現(xiàn),鎖分類介紹、AQS介紹、公平鎖非公平鎖介紹。
volatile關(guān)鍵字
volatile關(guān)鍵字是Java并發(fā)的最輕量級(jí)實(shí)現(xiàn),本質(zhì)上有兩個(gè)功能,在生成的匯編語(yǔ)句中加入LOCK關(guān)鍵字和內(nèi)存屏障 作用就是保證每一次線程load和write兩個(gè)操作,都會(huì)直接從主內(nèi)存中進(jìn)行讀取和覆蓋,而非普通變量從線程內(nèi)的工作空間(默認(rèn)各位已經(jīng)熟悉Java多線程內(nèi)存模型)
但它有一個(gè)很致命的缺點(diǎn),導(dǎo)致它的使用范圍不多,就是他只保證在讀取和寫入這兩個(gè)過(guò)程是線程安全的。如果我們對(duì)一個(gè)volatile修飾的變量進(jìn)行多線程下的自增操作,還是會(huì)出現(xiàn)線程安全問(wèn)題。根本原因在于volatile關(guān)鍵字無(wú)法對(duì)自增進(jìn)行安全性修飾,因?yàn)樽栽龇譃槿?,讀取-》+1-》寫入。中間多個(gè)線程同時(shí)執(zhí)行+1操作,還是會(huì)出現(xiàn)線程安全性問(wèn)題。
synchronized
鎖的優(yōu)化:偏向鎖、輕量級(jí)鎖、自旋鎖、重量級(jí)鎖
鎖的膨脹模型,以及鎖的優(yōu)化原理,為什么要這樣設(shè)計(jì)
與Concurrent包下的Lock的區(qū)別和聯(lián)系
Lock能夠?qū)崿F(xiàn)synchronized的所有功能,同時(shí),能夠?qū)崿F(xiàn)長(zhǎng)時(shí)間請(qǐng)求不到鎖時(shí)自動(dòng)放棄、通過(guò)構(gòu)造方法實(shí)現(xiàn)公平鎖、出現(xiàn)異常時(shí)synchronized會(huì)由JVM自動(dòng)釋放,而Lock必須手動(dòng)釋放,因此我們需要把unLock()方法放在finally{}語(yǔ)句塊中
concurrentHashMap
兩個(gè)hash過(guò)程,第一次找到所在的桶,并將桶鎖定,第二次執(zhí)行寫操作。
而讀操作不加鎖,JDK1.8中ConcurrentHashMap從1600行激增到6000行,中間做了很多細(xì)粒度的優(yōu)化,大家可以查一下。
鎖的優(yōu)化策略
① 讀寫分離
② 分段加鎖
③ 減少鎖持有的時(shí)間
④ 多個(gè)線程盡量以相同的順序去獲取資源
等等,這些都不是絕對(duì)原則,都要根據(jù)情況,比如不能將鎖的粒度過(guò)于細(xì)化,不然可能會(huì)出現(xiàn)線程的加鎖和釋放次數(shù)過(guò)多,反而效率不如一次加一把大鎖。這部分跟面試官談了很久
線程池的配置 Excutor 以及Connector的配置
線程池的種類、原理(threadpoolexecutor)、threadpoolexecutor的參數(shù)有哪些?
線程池的基本思想還是一種對(duì)象池的思想,開辟一塊內(nèi)存空間,里面存放了眾多(未死亡)的線程,池中線程執(zhí)行調(diào)度由池管理器來(lái)處理。當(dāng)有線程任務(wù)時(shí),從池中取一個(gè),執(zhí)行完成后線程對(duì)象歸池,這樣可以避免反復(fù)創(chuàng)建線程對(duì)象所帶來(lái)的性能開銷,節(jié)省了系統(tǒng)的資源。就好比原來(lái)去食堂打飯是每個(gè)人看誰(shuí)搶的贏,誰(shuí)先搶到誰(shuí)先吃,有了線程吃之后,就是排好隊(duì)形,今天我跟你關(guān)系好,你先來(lái)吃飯。比如:一個(gè)應(yīng)用要和網(wǎng)絡(luò)打交道,有很多步驟需要訪問(wèn)網(wǎng)絡(luò),為了不阻塞主線程,每個(gè)步驟都創(chuàng)建個(gè)線程,在線程中和網(wǎng)絡(luò)交互,用線程池就變的簡(jiǎn)單,線程池是對(duì)線程的一種封裝,讓線程用起來(lái)更加簡(jiǎn)便,只需要?jiǎng)?chuàng)一個(gè)線程池,把這些步驟像任務(wù)一樣放進(jìn)線程池,在程序銷毀時(shí)只要調(diào)用線程池的銷毀函數(shù)即可。
單個(gè)線程的弊端:
a. 每次new Thread新建對(duì)象性能差
b. 線程缺乏統(tǒng)一管理,可能無(wú)限制新建線程,相互之間競(jìng)爭(zhēng),及可能占用過(guò)多系統(tǒng)資源導(dǎo)致死機(jī)或者OOM,
c. 缺乏更多功能,如定時(shí)執(zhí)行、定期執(zhí)行、線程中斷。
Java提供的四種線程池的好處在于:
a. 重用存在的線程,減少對(duì)象創(chuàng)建、消亡的開銷,性能佳。
b. 可有效控制最大并發(fā)線程數(shù),提高系統(tǒng)資源的使用率,同時(shí)避免過(guò)多資源競(jìng)爭(zhēng),避免堵塞。
c. 提供定時(shí)執(zhí)行、定期執(zhí)行、單線程、并發(fā)數(shù)控制等功能。
Java通過(guò)Executors提供四種線程池,分別為:
newCachedThreadPool創(chuàng)建一個(gè)可緩存線程池,如果線程池長(zhǎng)度超過(guò)處理需要,可靈活回收空閑線程,若無(wú)可回收,則新建線程。
newFixedThreadPool 創(chuàng)建一個(gè)定長(zhǎng)線程池,可控制線程最大并發(fā)數(shù),超出的線程會(huì)在隊(duì)列中等待。
newScheduledThreadPool 創(chuàng)建一個(gè)定長(zhǎng)線程池,支持定時(shí)及周期性任務(wù)執(zhí)行。
newSingleThreadExecutor 創(chuàng)建一個(gè)單線程化的線程池,它只會(huì)用唯一的工作線程來(lái)執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級(jí))執(zhí)行。
(1). newCachedThreadPool
創(chuàng)建一個(gè)可緩存線程池,如果線程池長(zhǎng)度超過(guò)處理需要,可靈活回收空閑線程,若無(wú)可回收,則新建線程。線程池為無(wú)限大,當(dāng)執(zhí)行第二個(gè)任務(wù)時(shí)第一個(gè)任務(wù)已經(jīng)完成,會(huì)復(fù)用執(zhí)行第一個(gè)任務(wù)的線程,而不用每次新建線程。
(2). newFixedThreadPool
創(chuàng)建一個(gè)定長(zhǎng)線程池,可控制線程最大并發(fā)數(shù),超出的線程會(huì)在隊(duì)列中等待。
(3). newScheduledThreadPool
創(chuàng)建一個(gè)定長(zhǎng)線程池,支持定時(shí)及周期性任務(wù)執(zhí)行。ScheduledExecutorService比Timer更安全,功能更強(qiáng)大
(4). newSingleThreadExecutor
創(chuàng)建一個(gè)單線程化的線程池,它只會(huì)用唯一的工作線程來(lái)執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級(jí))執(zhí)行
線程通信、同步的方法。
Lock 比起 Synchronized 的優(yōu)勢(shì)在哪里;讀寫鎖的優(yōu)勢(shì)。
鎖的類型、重入鎖的原理(aqs)、aqs的常用方法
synchronized可重入嗎?
synchronized可以替代讀寫鎖嗎?
Lock內(nèi)部實(shí)現(xiàn)
終止線程有幾種方式?終止線程標(biāo)記變量為什么是 valotile 類型?
用過(guò)哪些并發(fā)的數(shù)據(jù)結(jié)構(gòu)? cyclicBarrier 什么功能?信號(hào)量作用?數(shù)據(jù)庫(kù)讀寫阻塞怎么解決
線程的中斷
線程的Interrupt中斷,其實(shí)只是修改線程的中斷位,并不會(huì)真正停止線程。(1)可以通過(guò)Thread的類方法interrupted檢查當(dāng)前線程是否中斷,但是會(huì)重置標(biāo)志位(2)通過(guò)調(diào)用Thread的普通方法isInterrupted來(lái)檢查中斷位,不會(huì)重置標(biāo)志位。
線程調(diào)用中斷方法不會(huì)停止程序,那么有什么用?
談了談線程池中,線程銷毀,假如沒(méi)有中斷那么就一直while檢查不斷執(zhí)行任務(wù)。如果中斷后,就return方法。就是return Runnable的run方法,線程運(yùn)行完畢自然就可以銷毀。(下來(lái)查資料看到真正的中斷用法)其實(shí)中斷線程有很多方法:(1)通過(guò)檢查標(biāo)志位用break退出循環(huán)(2)通過(guò)return退出run方法(3)通過(guò)對(duì)有些狀態(tài)中斷拋異常退出。
多線程,線程同步,鎖
sleep 與 wait 方法的區(qū)別
