HTTP TCP 對象的內存佈局java
對象頭(header)、實例數據(Instance Data)、對齊填充mysql
java對象頭裏的Mark Word裏默認存儲對象的HashCode、分代年齡和鎖標記位(包括鎖標誌位和是不是偏向鎖)面試
鎖一共4種狀態,級別從低到高分依次是:無鎖狀態,偏向鎖狀態,輕量級鎖狀態和重量級鎖狀態redis
一、內存劃分:棧內存,堆內存,方法區算法
二、堆內存劃分spring
新生代,老年代和永久代sql
新生代又可劃分爲Eden區,Survivor 1區和Survivor 2區。新建立的對象會分配在Eden區,在經歷一次Minor GC後會被移到Survivor 1區,再經歷一次Minor GC後會被移到Survivor 2區,直到升至老年代,須要注意的是,一些大對象(長字符串或數組)可能會直接存放到老年代shell
大多數狀況下,對象在新生代Eden區中分配,當Eden沒有足夠空間進行分配時,虛擬機將發起一次Minor GC(發生在新生代的垃圾收集動做)數據庫
新的對象實例會優先分配在新生代,在經歷幾回Minor GC後(默認15次),還存活的會被移至老年代編程
Full GC:指發生在老年代的GC
Minor GC發生在新生代,當Eden區沒有足夠空間時,會發起一次Minor GC,將Eden區中的存活對象移至Survivor區。Major GC發生在老年代,當升到老年代的對象大於老年代剩餘空間時會發生Major GC
全網惟一一個從0開始幫助Java開發者轉作大數據領域的公衆號~
大數據技術與架構或者搜索import_bigdata關注~
海量【java和大數據的面試題+視頻資料】整理在公衆號,關注後能夠下載~
一、定長與變長分離
定長:int,char,time
變長:varchar,text,blob
二、經常使用字段和不經常使用字段分離
三、一對多,須要關聯統計的字段上,添加冗餘字段(論壇版塊列表,回覆數)
四、列選擇原則:
1)字段類型優先級:整型>date,time>char,enum>varchar>blob.text
2)夠用就行,不用慷慨
3)儘可能避免使用NULL():在磁盤上佔用更大的空間,NULL()不利於索引,要用特殊的字符來表示
五、MYSQL索引類型:BTree索引、Hash索引
hash索引是在memory表裏的,即在內存中存在
hash索引的弊端:
1)沒法對範圍查詢進行優化
2)沒法利用前綴索引
3)沒法對排序進行優化
4)必須回行,即經過索引拿到表的位置,必須回到表中取數據
六、BTree索引常見誤區
1)在where條件經常使用的列上都加上索引——獨立索引只能用上一個
2)在多列上創建聯合索引後,查詢哪一個列,索引都能發揮做用——必須依照索引的順序,且知足左前綴要求
索引能夠提升查詢速度,排序速度和分組統計的速度
七、建立聯合索引
複製代碼 create table t4 ( c1 tinyint(1) not null default 0, c2 tinyint(1) not null default 0, c3 tinyint(1) not null default 0, c4 tinyint(1) not null default 0, c5 tinyint(1) not null default 0, index c1234(c1,c2,c3,c4) ); 複製代碼 八、分析索引的使用狀況:explain
Innodb和myisam都是使用的BTree索引
可是myisam使用的是非聚簇索引——索引表和數據表分離,其索引指向某行在磁盤上的位置,不一樣索引樹之間並沒有關聯
innodb使用的是聚簇索引,數據和索引一塊存放,不用回行,其索引,指向對主鍵的引用,非主鍵索引樹指向主鍵索引
葉子比較重,且主鍵無規律,容易出現葉分裂
索引覆蓋,優化的目的在於儘可能少從磁盤上拿數據 性能分析工具:show profiles—— set profiling=1
九、理想的索引:
1)查詢頻繁
2)區分度高
3)長度小
4)儘可能能覆蓋經常使用查詢字段
index(cat_id,price),index(cat_id,brand_id,shop_price);
十、索引與排序
排序可能發生兩種狀況:
1)對於索引覆蓋,直接在索引上查詢時,就是有順序的,using index
2)若是沒有索引,先取出臨時數據,造成臨時表作firesort(文件排序,可能在磁盤上,也可能在內存中)
咱們的爭取目標——取出來的數據自己就是有序的,利用索引來排序
對於myisam而言,對全部數據排序時並非每取一次索引而後去磁盤上取相應數據,而是將全部數據都取出來進行filesort
獨立的索引在每次查詢中只能使用一個,應該儘可能避免查詢中出現filesort
where 後面的字段和 order by後面的字段不一致的時候,也會出新filesort現象,由於獨立索引只能使用一個,查詢時用到了一個索引,在排序時就不能使用排序字段的索引了
十一、索引相關的操做語句
冗餘索引較爲常見,經常使用的爲兩個相同字段按前後順序分別創建不一樣的索引
十二、表修復——索引碎片及維護
方式一:nop操做,不對數據產生實際影響——alter table xxx engine InnoDB
方式二:optimize table name
注意: innodb來講,
1: 主鍵索引 既存儲索引值,又在葉子中存儲行的數據
2: 若是沒有主鍵, 則會Unique key作主鍵
3: 若是沒有unique,則系統生成一個內部的rowid作主鍵.
4: 像innodb中,主鍵的索引結構中,既存儲了主鍵值,又存儲了行數據,這種結構稱爲」聚簇索引」
1三、SQL語句優化
sql語句的執行時間花在哪了?
查找——沿着索引查找,慢者可能全表掃描
取出——查到行後,把數據取出來
如何查詢快?
1)查詢——聯合索引的順序,區分度,長度
2)取的快,索引覆蓋
3)傳輸更少,更少的行和列
儘可能走索引進行查詢
1四、explain 解釋一個查詢語句的執行計劃
字段詳解:
id:查詢的序號,代表select語句
複製代碼
select_type:
simple:不含子查詢
primary:含子查詢
dependent subquery:非from子查詢
derived:from子查詢
union 和 union result
table:查詢的表名
實際的表名,表的別名,derived(from類型的子查詢),null (union)
type:索引所發揮的做用
all:作全表掃描,where後面查詢條件列中沒有索引。利用索引來排序,可是取出來是全部的節點,因此也會出現all的狀況
Index:比all性能稍微好點,all掃描全部的數據行,至關於data_all,indux掃描全部的索引節點,至關於index_all
range:索引範圍掃描
ref:精準查詢,能夠直接引用到某些行數據
eq_ref:
const,system,null:查詢優化到常量級別,甚至不須要查詢時間,通常按主鍵查詢時,能出現這種狀況
possible_keys:可能用到的鍵
key:真正用到的鍵
key_len:表的長度
ref:兩表聯查時候的引用關係
rows:本次查詢返回的行數
extra:額外的信息
index:用到了索引覆蓋,效率很是高
using where:光靠索引定位不了,還得where進行判斷
using temporary:是指用上了臨時表,order by與group by不一樣列時,或group by,order by別的表的列
using filesort:文件排序(文件可能在磁盤,也可能在內存)
若是取出的列含有text,或者更大的如mediumtext等,filesort將會發生在磁盤上
show status like '%_table%':查看磁盤使用狀況
1五、In型子查詢的誤區:
mysql的查詢優化器,針對In型作了優化,被改爲了exists子查詢的執行效果,當goods表越大時,查詢速度越慢
改進:用鏈接查詢代替子查詢
explain select goods_id,g.cat_id,g.goods_name from goods as g
inner join (select cat_id from ecs_category where parent_id=6) as t
using(cat_id) \G
1六、from型子查詢
注意::內層from語句查到的臨時表, 是沒有索引的.
因此: from的返回內容要儘可能少.
1七、count(*)優化
1八、group by、order by
1九、union老是要產生臨時表
儘可能使用union all,不去重,不排序
20、limit 及翻頁優化
limit offset,N, 當offset很是大時, 效率極低,
緣由是mysql並非跳過offset行,而後單取N行,
而是取offset+N行,返回放棄前offset行,返回N行.
效率較低,當offset越大時,效率越低
show profiles;
set profiling=1;
show profile for query 5
儘可能沿着索引爬行
select id,name from lx_com where id>5000000 limit 10;
非要物理刪除,還要用offset精確查詢,還不限制用戶分頁,怎麼辦?
select id,name from lx_com inner join (select id from lx_com limit 5000000,10) as tmp using(id);
數據庫底層原理,調優
一、從空間上考慮用varchar,從效率上考慮,用char
varchar類型的實際長度,是它的值的實際長度+1,+1的字節用於保存實際用了多大長度
二、存儲過程
可移植性較差
定義存儲過程:
delimiter %
create procedure 過程名(參數1,參數2)
begin
sql語句
end
調用方式:
call 過程名(參數1,參數2)
存儲過程參數傳遞;
IN參數
in傳入參數,把參數傳遞到過程內部
特色:讀取外部變量值,且有效範圍僅限存儲過程內部
out:傳出參數
inout:傳入傳出參數
into:賦值
mysql中的變量
1)局部變量。
局部變量通常用在sql語句塊中,好比存儲過程的begin/end。其做用域僅限於該語句塊,在該語句塊執行完畢後,局部變量就消失了。
局部變量通常用declare來聲明,可使用default來講明默認值。
drop procedure if exists add;
create procedure add( in a int, in b int)
begin
declare c int default 0;
set c = a + b;
select c as c;
複製代碼
end;
2)用戶變量
用戶變量的做用域要比局部變量要廣。用戶變量能夠做用於當前整個鏈接,可是噹噹前鏈接斷開後,其所定義的用戶變量都會消失。
用戶變量使用以下(這裏咱們無須使用declare關鍵字進行定義,能夠直接這樣使用):
select @變量名
對用戶變量賦值有兩種方式,一種是直接用"="號,另外一種是用":="號。其區別在於使用set命令對用戶變量進行賦值時,兩種方式均可以使用;當使用select語句對用戶變量進行賦值時,只能使用":="方式,由於在select語句中,"="號被看做是比較操做符。
3)會話變量
4)全局變量
觸發器
與數據表有關,當表出現變化的時候(增、刪、改),自動執行其餘的特定的操做
觸發器的格式
語法:create trigger 觸發器名稱 觸發的時間 觸發的動做
on 表名 for each row 觸發器狀態
觸發器狀態:隨便起名字
觸發的時機:before/after 在執行動做以前仍是以後
觸發的動做:
指的激發觸發程序的語句類型:insert,update,delete
觸發器建立語法四要素:
1)監視地點(table)
2)監視事件(insert/update/delete)
3)觸發時間(after/before)
4)觸發事件(insert/update/delete)
查看觸發器:show triggers \G
查看觸發器建立過程:show create trigger triggername \G
事務:(只有InnoDB引擎支持)
開啓事務:START TRANSACTION
提交當前事務:COMMIT
關閉自動提交:set autocommit=0;
回滾:rollback
MySQL相關的配置文件:
主配置文件:/etc/my.cnf
進程通信文件:/var/lib/mysql/mysql.sock
日誌文件:/var/log/mysqld.log
進程ID文件:/var/run/mysqld/mysqld.pid
二進制文件:在my.cnf中增長
log-bin=mysql-bin.log
慢查詢日誌文件:在my.cnf中增長
log-slow-queries
存儲引擎層:存儲和提取數據以及事務處理
MyISAM的特性:
1)不支持事務,宕機時會破壞表
2)使用較小的內存和磁盤空間
3)基於表的鎖,表級鎖(加鎖與併發)表級鎖定影響性能
4)只緩存index,數據由os緩存
5)不支持外鍵約束,可是支持全文索引。
MyISAM調優精要:
一、設置合適的索引(緩存機制)
二、調整讀寫優先級,根據實際需求確保重要操做更優先執行
三、啓用延遲插入,改善大批量寫入性能
四、儘可能順序操做,讓insert數據都寫入到尾部,減小阻塞
五、下降併發數,減小對數據庫的訪問,使用消息隊列
六、對於相對靜態的數據庫數據,充分利用Query Cache或者memcached緩存服務能夠極大提升訪問速率
七、
InnoDB存儲引擎的特性
1)支持事務四個級別ACID
2)支持行鎖(行級鎖定)
3)聚簇索引
4)支持外鍵
5)支持崩潰數據自修復
6)具備高效的緩存特性,能緩存索引,也能緩存數據。
默認使用InnoDB引擎配置
default-storage-enigine=innodb
類加載器及其加載過程
MYSQL
ORACLE
多線程技術,各類鎖機制
一、moniterenter和moniterexit 指令對應於synchronized,更深一步是lock和unlock
二、執行moniterenter指令時,首先要嘗試獲取對象鎖。若是這個對象沒被鎖定,或者當前已經擁有了那個對象的鎖,把鎖的計數器加1,相應的,在執行moniterexit指令時會將計數器減1,當計數器爲0時,鎖就被釋放。
三、和synchronized相比,ReentrantLock增長了一些高級功能,主要有等待可中斷,可實現公平鎖,以及鎖能夠綁定多個條件。
四、自旋鎖:爲了讓線程等待,只需讓線程執行一個忙循環(自旋),但並不放棄處理器的執行時間,這項技術就是自旋鎖
自旋鎖能夠在時間上和自旋次數上進行控制,自適應自旋鎖
五、
大數據相關組件及其原理
設計模式
zookeeper原理
數據庫和緩存保持數據的一致性
Concurrent包
虛擬機和調優
緩存一致性問題(如何解決數據庫和redis緩存的雙寫操做)
一致性Hash算法
內存高佔用率分析
java內存模型
一、Java內存模型規定了全部變量都存儲在主內存中,每條線程還有本身的工做內存,線程的工做內存中保存了被該線程使用到的變量的主內存副本拷貝,線程對變量的全部操做都必須在工做內存中進行,而不能直接讀寫準內存中的變量。
二、內存間交互操做
lock、unlock
read、load:二者不能單獨出現
use、assign
store、write:二者不能單獨出現
3.volatile不保證原子性
特性1:保證此變量對全部線程的可見性
特性2:禁止指令重排序優化
Executor
1.Executor框架的結構
2.ThreadPoolExecutor
ThreadPoolExecutor一般使用工廠類Executors來建立,能夠建立的三種類型
SingleThreadExecutor:只有一個線程,適用於須要保證順序地執行各個任務,而且在任意時間點,不會有多個線程是活動的應用場景
FixedThreadPool:用於須要限制當前線程數量的應用場景,它適用於負載比較重的服務器
CachedThreadPool:是大小無界的線程池,適用於執行不少的短時間異步任務的小程序,或者是負載較輕的服務器
HashMap和ConcurrentHashMap
在併發編程中使用HashMap可能致使程序死循環,而使用線程安全的HashTable效率又很是低下
在多線程中使用HashMap進行put操做會引發死循環,致使CPU利用率接近100%,由於多線程會致使HashMap的Entry鏈表造成環形數據結構,一旦造成環形數據結構,Entry的next節點永遠不爲空。
ConcurrentHashMap的鎖分段技術可有效提高併發訪問率
chm由Segment數組結構和HashEntry數組結構組成,Segment是一種可重入鎖(ReentrantLock)。
Segment的結構和HashMap相似,是一種數組和鏈表結構,一個Segment裏包含一個HashEntry數組,每一個HashEntry是一個鏈表結構的元素。
定位Segment:
在插入和獲取元素的時候,必須先經過散列算法定位到Segment,之因此進行再散列,目的是減小散列衝突,使元素可以均勻的分佈在不一樣的Segment上,從而提升容器的存取效率,經過這種再散列能讓數字的每一位都參加到散列運算當中,從而減小散列衝突。
get操做:get操做不須要加鎖,由於get方法中要使用的共享變量都定義成立volatile類型,所以能夠在多線程中保持可見性,能夠被多線程同時讀
由於根據Java內存模型的先行發生原則,對volatile字段的寫入操做先於讀操做,即便兩個線程同時修改和獲取volatile變量,get操做也能拿到最新的值。
put操做:判斷是否須要對HashEntry數組進行擴容,第二步定位添加元素的位置
先行發生原則
1)程序次序規則
2)管程鎖定規則
3)volatile變量規則:對一個volatile變量的寫操做先行發生於後面這個變量的讀操做
Synchronized
同步代碼塊使用了 monitorenter 和 monitorexit 指令實現。
同步方法中依靠方法 修飾符上的 ACC_SYNCHRONIZED 實現
鎖的四種狀態:無鎖狀態,偏向鎖狀態,輕量級鎖狀態,重量級鎖狀態
輕量級鎖能提高程序同步性能的依據是「對於絕大部分的鎖,在整個同步週期內都是不存在競爭的」,輕量級鎖使用CAS 操做避免了使用互斥量的開銷
monitor是線程私有的數據結構,每個線程都有一個可用的monitor列表,同時還有一個全局可用的列表
每一個線程的當前棧幀中都有一個Lock Record鎖記錄,用於存儲鎖對象目前的Mark Word的拷貝
虛擬機將使用CAS操做將Mark Word更新爲指向Lock Record的指針,若是成功,則擁有輕量級鎖
若是有兩條以上的線程爭用同一個鎖,那輕量級鎖就再也不有效,要膨脹爲重量級鎖
輕量級鎖:利用了CPU原語Compare-And-Swap(CAS,彙編指令CMPXCHG)
若是說輕量級鎖是在無競爭的狀況下使用CAS操做去消除同步使用的互斥量,那偏向鎖就是在無競爭的狀況下把整個同步都消除掉,連CAS操做都不作了
CAS(Compare and swap)原理
思想,三個參數,一個當前內存值V、舊的預期值A、即將更新的值B,當且僅當預期值A和內存值V相同時,將內存值修改成B並返回true,不然什麼都不作,並返回false
CAS是經過unsafe類的compareAndSwap方法實現的
Unsafe是CAS的核心類,因爲Java方法沒法直接訪問底層系統,須要經過本地(native)方法來訪問,Unsafe至關於一個後門,基於該類能夠直接操做特定內存的數據
compareAndSwap:第一個參數是要修改的對象,第二個參數是對象中要修改變量的偏移量,第三個參數是修改以前的值,第四個參數是預想修改後的值
CAS的缺點:ABA問題
若是變量V初次讀取的時候是A,而且在準備賦值的時候檢查到它仍然是A,那能說明它的值沒有被其餘線程修改過了嗎?
解決辦法:java併發包中提供了一個帶有標記的原子引用類AtomicStampedReference,它能夠經過控制變量值的版原本保證CAS的正確性
LOCK(AQS)
當經過lockInterruptibly()方法獲取某個鎖時,若是不能獲取到,只有進行等待的狀況下,是能夠響應中斷的。
而用synchronized修飾的話,當一個線程處於等待某個鎖的狀態,是沒法被中斷的,只有一直等待下去。
REDIS哨兵的主要做用:集羣監控和故障轉移 )
qps多少,99線多少 qps 5萬 / 500-800ms string stringbuffer stringbuilder區別
string a = "abc" string b = new String("abc"), a == b和 a.equals(b)返回什麼值,爲何
hashmap hashtable ConcurrentHashMap區別
hashmap結構,默認長度
ConcurrentHashMap結構,是否和hashmap同樣,段鎖的實現方式,
數據庫隔離級別都有哪一個,mysql默認隔離級別是什麼,不可重複讀和幻讀是什麼意思
數據庫的存儲引擎都用過哪些,什麼區別,他們的索引什麼區別。innodb的主鍵索引和輔助索引的區別,組合索引,哪一種方式走索引
mysql的執行計劃都有哪些字段
spring事物傳播級別概念,記住概念,實現方式,
spring 有哪些特性,ioc和aop是什麼意思,aop使用場景,spring中aop是怎麼實現的,cglib和javasist區別
@@@@@@spring中兩個對象雙向引用是怎麼實現的 第一種,解決setter對象的依賴,就是說在A類須要設置B類,B類須要設置C類,C類須要設置A類,這時就出現一個死循環,
spring的解決方案是,初始化A類時把A類的初始化Bean放到緩存中,而後set B類,再把B類的初始化Bean放到緩存中,
而後set C類,初始化C類須要A類和B類的Bean,這時不須要初始化,只須要從緩存中取出便可.
該種僅對single做用的Bean起做用,由於prototype做用的Bean,Spring不對其作緩存
第二種,解決構造器中對其它類的依賴,建立A類須要構造器中初始化B類,建立B類須要構造器中初始化C類,建立C類須要構造器中又要初始化A類,於是造成一個死循環,Spring的解決方案是,把建立中的Bean放入到一個「當前建立Bean池」中,在初始化類的過程當中,若是發現Bean類已存在,就拋出一個「BeanCurrentInCreationException」的異常
@@@@給你一個加減乘除的簽名 int operator(int a, int b, string oprator),你怎麼實現這個功能,策略算法
@@@@設計一個車,能夠是小汽車,拖拉機,等車型,它能夠行走在公路,泥路,山路上等,你怎麼設計。一個設計模式
@@@jvm內存分爲幾個區,哪寫區會有OOM異常,堆包含哪幾塊。大家用的什麼垃圾回收策略, SerialOld 做爲CMS失敗時候的後備收集器。
說下cms的幾個步驟,哪一個步驟會STW,CMS的優勢缺點,CMS怎麼分析數據是否可達,GC ROOT怎麼找的,CMS處理失敗後怎麼繼續處理,PALL OLD
老年代怎麼分配的空間,(碰撞指針,仍是空閒列表)
線程都有什麼狀態
synchronized怎麼實現的,lock怎麼實現的,他們的優缺點 1.可重入鎖
若是鎖具有可重入性,則稱做爲可重入鎖。像synchronized和ReentrantLock都是可重入鎖,可重入性在我看來實際上代表了鎖的分配機制:基於線程的分配,而不是基於方法調用的分配。
2.可中斷鎖
可中斷鎖:顧名思義,就是能夠相應中斷的鎖。
在Java中,synchronized就不是可中斷鎖,而Lock是可中斷鎖。
若是某一線程A正在執行鎖中的代碼,另外一線程B正在等待獲取該鎖,可能因爲等待時間過長,線程B不想等待了,想先處理其餘事情,咱們可讓它中斷本身或者在別的線程中中斷它,這種就是可中斷鎖。
3.公平鎖和非公平鎖
公平鎖以請求鎖的順序來獲取鎖,非公平鎖則是沒法保證按照請求的順序執行。synchronized就是非公平鎖,它沒法保證等待的線程獲取鎖的順序。而對於ReentrantLock和ReentrantReadWriteLock,它默認狀況下是非公平鎖,可是能夠設置爲公平鎖。
參數爲true時表示公平鎖,不傳或者false都是爲非公平鎖。
ReentrantLock lock = new ReentrantLock(true); 4.讀寫鎖
讀寫鎖將對一個資源(好比文件)的訪問分紅了2個鎖,一個讀鎖和一個寫鎖。
正由於有了讀寫鎖,才使得多個線程之間的讀操做不會發生衝突。
ReadWriteLock就是讀寫鎖,它是一個接口,ReentrantReadWriteLock實現了這個接口。
能夠經過readLock()獲取讀鎖,經過writeLock()獲取寫鎖。 1.synchronized
優勢:實現簡單,語義清晰,便於JVM堆棧跟蹤,加鎖解鎖過程由JVM自動控制,提供了多種優化方案,使用更普遍
缺點:悲觀的排他鎖,不能進行高級功能
2.lock
優勢:可定時的、可輪詢的與可中斷的鎖獲取操做,提供了讀寫鎖、公平鎖和非公平鎖
缺點:需手動釋放鎖unlock,不適合JVM進行堆棧跟蹤
3.相同點
都是可重入鎖
volatile特性,i++怎麼實現的 0: iconst_0 // 生成整數0 1: istore_1 // 將整數0賦值給1號存儲單元(即變量i) 2: iload_1 // 將1號存儲單元的值加載到數據棧(此時 i=0,棧頂值爲0) 3: iinc 1, 1 // 1號存儲單元的值+1(此時 i=1) 6: istore_2 // 將數據棧頂的值(0)取出來賦值給2號存儲單元(即變量j,此時i=1,j=0) 7: return // 返回時:i=1,j=0 偏向鎖,輕量級鎖,重量級鎖瞭解嗎 自旋鎖
互斥同步對性能最大的影響是阻塞的實現,掛起線程和恢復線程的操做都須要轉入內核態中完成,這些操做給系統的併發性能帶來了很大的壓力。而在不少應用上,共享數據的鎖定狀態只會持續很短的一段時間。若實體機上有多個處理器,能讓兩個以上的線程同時並行執行,咱們就可讓後面請求鎖的那個線程原地自旋(不放棄CPU時間),看看持有鎖的線程是否很快就會釋放鎖。爲了讓線程等待,咱們只須讓線程執行一個忙循環(自旋),這項技術就是自旋鎖。
若是鎖長時間被佔用,則浪費處理器資源,所以自旋等待的時間必需要有必定的限度,若是自旋超過了限定的次數仍然沒有成功得到鎖,就應當使用傳統的方式去掛起線程了(默認10次)。
JDK1.6引入自適應的自旋鎖:自旋時間再也不固定,由前一次在同一個鎖上的自旋時間及鎖的擁有者的狀態來決定。若是在同一個鎖對象上,自旋等待剛剛成功得到過鎖,而且持有鎖的線程正在運行中,那麼虛擬機就會認爲此次自旋也頗有可能再次成功,進而它將容許自旋等待持續相對更長的時間。
鎖削除
鎖削除是指虛擬機即時編譯器在運行時,對一些代碼上要求同步,可是被檢測到不可能存在共享數據競爭的鎖進行削除(主要斷定依據來源於逃逸分析的數據支持,若是判斷到一段代碼中,在堆上的全部數據都不會逃逸出去被其餘線程訪問到,那就能夠把它們看成棧上數據對待,認爲它們是線程私有的,同步加鎖天然就無須進行)。
鎖膨脹
若是一系列的連續操做都對同一個對象反覆加鎖和解鎖,甚至加鎖操做是出如今循環體中的,那即便沒有線程競爭,頻繁地進行互斥同步操做也會致使沒必要要的性能損耗。 若是虛擬機探測到有這樣一串零碎的操做都對同一個對象加鎖,將會把加鎖同步的範圍擴展(膨脹)到整個操做序列的外部(由屢次加鎖編程只加鎖一次)。
輕量級鎖
輕量級鎖並非用來代替重量級鎖(傳統鎖機制,如互斥等)的,目的是在沒有多線程競爭的前提下,減小傳統的重量級鎖使用操做系統互斥量產生的性能消耗。
HotSpot虛擬機的對象頭(Object Header)分爲兩部分信息,第一部分用於存儲對象自身的運行時數據,如哈希碼(HashCode)、GC分代年齡(Generational GC Age)等,這部分數據的長度在32位和64位的虛擬機中分別爲32個和64個Bits,官方稱它爲「Mark Word」,它是實現輕量級鎖和偏向鎖的關鍵。另一部分用於存儲指向方法區對象類型數據的指針,若是是數組對象的話,還會有一個額外的部分用於存儲數組長度。
Mark Word被設計成一個非固定的數據結構以便在極小的空間內存儲儘可能多的信息,它會根據對象的狀態複用本身的存儲空間。例如在32位的HotSpot虛擬機中對象未被鎖定的狀態下,Mark Word的32個Bits空間中的25Bits用於存儲對象哈希碼(HashCode),4Bits用於存儲對象分代年齡,2Bits用於存儲鎖標誌位,1Bit固定爲0,在其餘狀態(輕量級鎖定、重量級鎖定、GC標記、可偏向)下Mark Word的存儲內容以下表所示。
存儲內容標誌位狀態 對象Hash值、對象分代年齡 指向鎖記錄的指針00輕量級鎖定 指向重量級鎖指針10膨脹(重量級鎖定) 偏向線程ID、偏向時間戳、對象分代年齡01可偏向 鎖過程
在代碼進入同步塊的時候,若是此同步對象沒有被鎖定(鎖標誌位爲「01」狀態),虛擬機首先將在當前線程的棧幀中創建一個名爲鎖記錄(Lock Record)的空間,用於存儲鎖對象目前的Mark Word的拷貝(官方把這份拷貝加了一個Displaced前綴,即Displaced Mark Word),這時候線程堆棧與對象頭的狀態以下圖所示。
而後,虛擬機將使用CAS操做嘗試將對象的Mark Word更新爲指向Lock Record的指針。若是這個更新動做成功,那麼這個線程就擁有了該對象的鎖,而且對象Mark Word的鎖標誌位(Mark Word的最後兩個Bits)將轉變爲「00」,即表示此對象處於輕量級鎖定狀態,這時候線程堆棧與對象頭的狀態以下圖所示。
若是這個更新操做失敗了,虛擬機首先會檢查對象的Mark Word是否指向當前線程的棧幀,若是是就說明當前線程已經擁有了這個對象的鎖,那就能夠直接進入同步塊繼續執行,不然說明這個鎖對象已經被其餘線程搶佔了。若是有兩條以上的線程爭用同一個鎖,那輕量級鎖就再也不有效,要膨脹爲重量級鎖,鎖標誌的狀態值變爲「10」,Mark Word中存儲的就是指向重量級鎖(互斥量)的指針,後面等待鎖的線程也要進入阻塞狀態。
解鎖過程
解鎖過程也是經過CAS操做來進行的,若是對象的Mark Word仍然指向着線程的鎖記錄,那就用CAS操做把對象當前的Mark Word和線程中複製的Displaced Mark Word替換回來,若是替換成功,整個同步過程就完成了。若是替換失敗,說明有其餘線程嘗試過獲取該鎖,那就要在釋放鎖的同時,喚醒被掛起的線程。
輕量級鎖小結
輕量級鎖能提高程序同步性能的依據是「對於絕大部分的鎖,在整個同步週期內都是不存在競爭的」,這是一個經驗數據。若是沒有競爭,輕量級鎖使用CAS操做避免了使用互斥量的開銷,但若是存在鎖競爭,除了互斥量的開銷外,還額外發生了CAS操做,所以在有競爭的狀況下,輕量級鎖會比傳統的重量級鎖更慢。
偏向鎖
目的是消除數據在無競爭狀況下的同步原語,進一步提升程序的運行性能。若是說輕量級鎖是在無競爭的狀況下使用CAS操做去消除同步使用的互斥量,那偏向鎖就是在無競爭的狀況下把整個同步都消除掉,連CAS操做都不作了。
偏向鎖會偏向於第一個得到它的線程(Mark Word中的偏向線程ID信息),若是在接下來的執行過程當中,該鎖沒有被其餘的線程獲取,則持有偏向鎖的線程將永遠不須要再進行同步。
假設當前虛擬機啓用了偏向鎖(啓用參數-XX:+UseBiasedLocking,JDK 1.6的默認值),當鎖對象第一次被線程獲取的時候,虛擬機將會把對象頭中的標誌位設爲「01」,即偏向模式。同時使用CAS操做把獲取到這個鎖的線程的ID記錄在對象的Mark Word之中,若是CAS操做成功,持有偏向鎖的線程之後每次進入這個鎖相關的同步塊時,虛擬機均可以再也不進行任何同步操做(例如Locking、Unlocking及對Mark Word的Update等)。 當有另一個線程去嘗試獲取這個鎖時,偏向模式就宣告結束。根據鎖對象目前是否處於被鎖定的狀態,撤銷偏向(Revoke Bias)後恢復到未鎖定(標誌位爲「01」)或輕量級鎖定(標誌位爲「00」)的狀態,後續的同步操做就如上面介紹的輕量級鎖那樣執行。偏向鎖、輕量級鎖的狀態轉化及對象Mark Word的關係以下圖所示。
偏向鎖能夠提升帶有同步但無競爭的程序性能。它一樣是一個帶有效益權衡(Trade Off)性質的優化,也就是說它並不必定老是對程序運行有利,若是程序中大多數的鎖都老是被多個不一樣的線程訪問,那偏向模式就是多餘的。
特別說明:尊重做者的勞動成果,轉載請註明出處哦~~~http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt364
aqs瞭解嗎,cas實現方式,自旋的缺點,jvm怎麼優化自旋(自旋優化這個問題我的以爲應該放在同步快上去問) pinlock不會使線程狀態發生切換,mutex在獲取不到鎖的時候會選擇sleep。
mutex獲取鎖分爲兩階段,第一階段在用戶態採用spinlock鎖總線的方式獲取一次鎖,若是成功當即返回;不然進入第二階段,調用系統的futex鎖去sleep,當鎖可用後被喚醒,繼續競爭鎖。
Spinlock優勢:沒有昂貴的系統調用,一直處於用戶態,執行速度快。
Spinlock缺點:一直佔用cpu,並且在執行過程當中還會鎖bus總線,鎖總線時其餘處理器不能使用總線。
Mutex優勢:不會忙等,得不到鎖會sleep。
Mutex缺點:sleep時會陷入到內核態,須要昂貴的系統調用。 threadlocal實現方式
二叉樹遍歷方式,哪一個遍歷方式高,時間複雜度多少,紅黑色實現方式,解決啥問題 對二叉樹的遍歷訪問且僅訪問全部結點一次,因此時間複雜度爲O(n)
Morris算法在遍歷的時候避免使用了棧結構,而是讓下層到上層有指針,具體是經過底層節點指向NULL的空閒指針返回上層的某個節點,從而完成下層到上層的移動O(1)
手寫快速排序,跳錶,TOP N問題
雙主數據庫主鍵怎麼生成的,雪花算法有啥問題
dubbo有什麼優勢,dubbo默認協議,默認序列化方式
缺省協議,使用基於netty3.2.2+hessian3.2.1交互。
鏈接個數:單鏈接
鏈接方式:長鏈接
傳輸協議:TCP
傳輸方式:NIO異步傳輸
序列化:Hessian二進制序列化
適用範圍:傳入傳出參數數據包較小(建議小於100K),消費者比提供者個數多,單一消費者沒法壓滿提供者,儘可能不要用dubbo協議傳輸大文件或超大字符串。
適用場景:常規遠程服務方法調用
複製代碼
zk算法
redis主從同步機制,若是主掛了,怎麼在從節點中選擇一個節點做爲主節點
熔斷機制中,線程池隔離和信號隔離的實現方式,設計一個熔斷器
mq堆積問題怎麼解決
二叉樹遍歷shell文件排序jvm調優(怎麼調) hashmap和hashtable區別聊項目問算法 算法:N * N 數組的的斜槓輸出
非算法:主要是線程併發相關
synchronized 的實現原理 lock的實現原理
線程池的調優 newCachedThreadPool() newFixedThreadPool等的區別和參數調優
hashtable hashmap的底層實現機制
spring事務的實現原理
mysql鎖機制,索引的類型,主鍵索引和普通索引的區別 主鍵必定是惟一性索引,惟一性索引並不必定就是主鍵 一個表中能夠有多個惟一性索引,但只能有一個主鍵. 主鍵列不容許空值,而惟一性索引列容許空值.
mysql 多個索引作where條件,執行隨機指定一個where有索引,order 有索引,where索引沒起做用mysql 創建多個索引,update多個索引操做,有可能索引 dubbo自定義線程池,阻塞隊列長度設置 dubbo默認提供了三種線程池,分別是 fixed 固定大小線程池,啓動時創建線程,不關閉,一直持有。 (默認,100個) cached 緩存線程池,空閒一分鐘自動刪除,須要時重建。 limited 可伸縮線程池,但池中的線程數只會增加不會收縮。(爲避免收縮時忽然來了大流量引發的性能問題)。 dubbo機房,網絡異常,所有斷網幾分鐘,後恢復,會有什麼問題: 長鏈接會斷開,致使客戶端不重連,須要重啓 redis mysql同步mysql int類型索引字段a,查詢條件, 爲字符串會走索引嗎,相反條件呢 權限設計 線程池超時時間怎麼弄 用submit方法,返回一個Future,而後調用Future中的V get(long timeout, TimeUnit unit)方法,timeout就是超時時間,超時沒返回結果就會報異常,捕獲異常,而後調用cancel方法
全網惟一一個從0開始幫助Java開發者轉作大數據領域的公衆號~
大數據技術與架構或者搜索import_bigdata關注~
海量【java和大數據的面試題+視頻資料】整理在公衆號,關注後能夠下載~