A. java中有哪些鎖,區別是什麼
【1】公平所和非公平所。
公平鎖:是指按照申請鎖的順序來獲取鎖,
非公平所:線程獲取鎖的順序不一定按照申請鎖的順序來的。
//默認是不公平鎖,傳入true為公平鎖,否則為非公平鎖
ReentrantLock reentrantLock = new ReetrantLock();
1
2
【2】共享鎖和獨享鎖
獨享鎖:一次只能被一個線程所訪問
共享鎖:線程可以被多個線程所持有。
ReadWriteLock 讀鎖是共享鎖,寫鎖是獨享鎖。
【3】樂觀鎖和悲觀鎖。
樂觀鎖:對於一個數據的操作並發,是不會發生修改的。在更新數據的時候,會嘗試採用更新,不斷重入的方式,更新數據。
悲觀鎖:對於同一個數據的並發操作,是一定會發生修改的。因此對於同一個數據的並發操作,悲觀鎖採用加鎖的形式。悲觀鎖認為,不加鎖的操作一定會出問題,
【4】分段鎖
1.7及之前的concurrenthashmap。並發操作就是分段鎖,其思想就是讓鎖的粒度變小。
【5】偏向鎖是指一段同步代碼一直被一個線程所訪問,那麼該線程會自動獲取鎖。降低獲取鎖的代價
輕量級鎖
重量級鎖
【6】自旋鎖
自旋鎖
B. JAVA編程同步,加鎖如何實現,有何優缺點
同步鎖「synchronize」,手動鎖Lock
synchronize:自動鎖住,自動開鎖。(自動都是建立在一定的條件上的)
Lock:手動,手動鎖住,手動開鎖
具體如何實現,這里不好說,一時說不清,自行搜索。
C. java中 請問我應該如何如何鎖這段代碼才符合要求
public Object getObject(String key,Object o) {
synchronized (map) {
if(map.get(key)==null) {
map.put(key,o)
}else {
return map.get(key);
}}// 格式沒法弄,自己弄一下
}
// demol0326 的回答意思使用MyTest的實例來加鎖,但是map是static的,無法鎖住
// MyTest的多個實例在多個線程中的請求
//禾木雙子 :如果A線程在getObject方法的第二行停止,此時B線程進入getObject後執行部分代碼, 此時B線程停止,A線程啟動,他不會執行'多線程處理', 仍然有線程線程安全問題,(想像一下更多的線程進入該方法的情況,num甚至會得到負值)
D. 關於JAVA里的加鎖synchronized
1.凡使用synchronized標記的方法,比如 public synchronized void func1() { .... },則同時只有一個線程能夠運行這個方法。比如,線程1正在運行func1,則其他線程需要運行func1的話,會卡住,等線程1運行func1結束後,其他線程中,才會有一個幸運兒成功爭取到運行func1的資格,然後這個幸運兒線程開始運行func1。沒有爭取到運行資格的其他線程,會繼續等待。
2.你的例子中,被鎖定的是 方法 m1,而不是屬性b。所以,m1的synchronized加鎖操作,與b沒有半點毛錢關系。
3.要實現你的鎖b想法,其實很簡單。去買一件貞操寶甲來就行了。開玩笑,哈哈。要鎖b,把main方法里的tt.m2()修改為tt.m1()。
4.以後別用「b」作為變數,總覺得怪怪了。也許你現在還沒長大,很單純。但大人的世界裡,「b」是一種不文雅但又對人類的未來有重要作用的東西。建議用cb來代替b。
E. Java鎖有哪些種類,以及區別
一、公平鎖/非公平鎖
公平鎖是指多個線程按照申請鎖的順序來獲取鎖。
非公平鎖是指多個線程獲取鎖的順序並不是按照申請鎖的順序,有可能後申請的線程比先申請的線程優先獲取鎖。有可能,會造成優先順序反轉或者飢餓現象。
對於Java ReentrantLock而言,通過構造函數指定該鎖是否是公平鎖,默認是非公平鎖。非公平鎖的優點在於吞吐量比公平鎖大。
對於Synchronized而言,也是一種非公平鎖。由於其並不像ReentrantLock是通過AQS的來實現線程調度,所以並沒有任何辦法使其變成公平鎖。
二、可重入鎖
可重入鎖又名遞歸鎖,是指在同一個線程在外層方法獲取鎖的時候,在進入內層方法會自動獲取鎖。說的有點抽象,下面會有一個代碼的示例。
對於Java ReentrantLock而言, 他的名字就可以看出是一個可重入鎖,其名字是Re entrant Lock重新進入鎖。
對於Synchronized而言,也是一個可重入鎖。可重入鎖的一個好處是可一定程度避免死鎖。
synchronized void setA() throws Exception{
Thread.sleep(1000);
setB();
}
synchronized void setB() throws Exception{
Thread.sleep(1000);
}
上面的代碼就是一個可重入鎖的一個特點,如果不是可重入鎖的話,setB可能不會被當前線程執行,可能造成死鎖。
三、獨享鎖/共享鎖
獨享鎖是指該鎖一次只能被一個線程所持有。
共享鎖是指該鎖可被多個線程所持有。
對於Java
ReentrantLock而言,其是獨享鎖。但是對於Lock的另一個實現類ReadWriteLock,其讀鎖是共享鎖,其寫鎖是獨享鎖。
讀鎖的共享鎖可保證並發讀是非常高效的,讀寫,寫讀 ,寫寫的過程是互斥的。
獨享鎖與共享鎖也是通過AQS來實現的,通過實現不同的方法,來實現獨享或者共享。
對於Synchronized而言,當然是獨享鎖。
四、互斥鎖/讀寫鎖
上面講的獨享鎖/共享鎖就是一種廣義的說法,互斥鎖/讀寫鎖就是具體的實現。
互斥鎖在Java中的具體實現就是ReentrantLock
讀寫鎖在Java中的具體實現就是ReadWriteLock
五、樂觀鎖/悲觀鎖
樂觀鎖與悲觀鎖不是指具體的什麼類型的鎖,而是指看待並發同步的角度。
悲觀鎖認為對於同一個數據的並發操作,一定是會發生修改的,哪怕沒有修改,也會認為修改。因此對於同一個數據的並發操作,悲觀鎖採取加鎖的形式。悲觀的認為,不加鎖的並發操作一定會出問題。
樂觀鎖則認為對於同一個數據的並發操作,是不會發生修改的。在更新數據的時候,會採用嘗試更新,不斷重新的方式更新數據。樂觀的認為,不加鎖的並發操作是沒有事情的。
從上面的描述我們可以看出,悲觀鎖適合寫操作非常多的場景,樂觀鎖適合讀操作非常多的場景,不加鎖會帶來大量的性能提升。
悲觀鎖在Java中的使用,就是利用各種鎖。
樂觀鎖在Java中的使用,是無鎖編程,常常採用的是CAS演算法,典型的例子就是原子類,通過CAS自旋實現原子操作的更新。
六、分段鎖
分段鎖其實是一種鎖的設計,並不是具體的一種鎖,對於ConcurrentHashMap而言,其並發的實現就是通過分段鎖的形式來實現高效的並發操作。
我們以ConcurrentHashMap來說一下分段鎖的含義以及設計思想,ConcurrentHashMap中的分段鎖稱為Segment,它即類似於HashMap(JDK7與JDK8中HashMap的實現)的結構,即內部擁有一個Entry數組,數組中的每個元素又是一個鏈表;同時又是一個ReentrantLock(Segment繼承了ReentrantLock)。
當需要put元素的時候,並不是對整個hashmap進行加鎖,而是先通過hashcode來知道他要放在那一個分段中,然後對這個分段進行加鎖,所以當多線程put的時候,只要不是放在一個分段中,就實現了真正的並行的插入。
但是,在統計size的時候,可就是獲取hashmap全局信息的時候,就需要獲取所有的分段鎖才能統計。
分段鎖的設計目的是細化鎖的粒度,當操作不需要更新整個數組的時候,就僅僅針對數組中的一項進行加鎖操作。
七、偏向鎖/輕量級鎖/重量級鎖
這三種鎖是指鎖的狀態,並且是針對Synchronized。在Java
5通過引入鎖升級的機制來實現高效Synchronized。這三種鎖的狀態是通過對象監視器在對象頭中的欄位來表明的。
偏向鎖是指一段同步代碼一直被一個線程所訪問,那麼該線程會自動獲取鎖。降低獲取鎖的代價。
輕量級鎖是指當鎖是偏向鎖的時候,被另一個線程所訪問,偏向鎖就會升級為輕量級鎖,其他線程會通過自旋的形式嘗試獲取鎖,不會阻塞,提高性能。
重量級鎖是指當鎖為輕量級鎖的時候,另一個線程雖然是自旋,但自旋不會一直持續下去,當自旋一定次數的時候,還沒有獲取到鎖,就會進入阻塞,該鎖膨脹為重量級鎖。重量級鎖會讓其他申請的線程進入阻塞,性能降低。
八、自旋鎖
在Java中,自旋鎖是指嘗試獲取鎖的線程不會立即阻塞,而是採用循環的方式去嘗試獲取鎖,這樣的好處是減少線程上下文切換的消耗,缺點是循環會消耗CPU。
典型的自旋鎖實現的例子,可以參考自旋鎖的實現
F. java 鏈接redis 怎麼加鎖
我介紹一下Redis分布式鎖吧:
一、定義redis實現分布式鎖的介面
[java]viewplainprint?
packagecom.iol.common.util.concurrent.locks;
importjava.io.Serializable;
/**
*Description:定義redis實現分布式鎖的演算法<br/>
*_SMALL_TAIL.<br/>
*ProgramName:IOL_SMALL_TAIL<br/>
*Date:2015年11月8日
*
*@author王鑫
*@version1.0
*/
{
/**
*加鎖演算法<br/>
*@paramkey
*@return
*/
publicbooleanlock(Stringkey);
/**
*解鎖演算法<br/>
*@paramkey
*@return
*/
publicbooleanunLock(Stringkey);
}
二、redis分布式鎖基礎演算法實現
[java]viewplainprint?
packagecom.iol.common.util.concurrent.locks.arithmetic;
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
importcom.iol.common.util.concurrent.locks.IRedisComponent;
importcom.iol.common.util.concurrent.locks.IRedisLockArithmetic;
/**
*Description:redis分布式鎖基礎演算法實現<br/>
*_SMALL_TAIL.<br/>
*ProgramName:IOL_SMALL_TAIL<br/>
*Date:2015年11月9日
*
*@author王鑫
*@version1.0
*/
{
/**
*serialVersionUID
*/
=-8333946071502606883L;
privateLoggerlogger=LoggerFactory.getLogger(RedisLockBaseArithmetic.class);
/**
*redis操作方法
*/
;
/**
*超時時間,以毫秒為單位<br/>
*默認為5分鍾
*/
privatelongovertime=5*60*1000L;
/**
*休眠時長,以毫秒為單位<br/>
*默認為100毫秒
*/
privatelongsleeptime=100L;
/**
*當前時間
*/
privatelongcurrentLockTime;
/**
*@
*/
publicvoidsetRedisComp(IRedisComponentredisComp){
this.redisComp=redisComp;
}
/**
*@paramovertimetheovertimetoset
*/
publicvoidsetOvertime(longovertime){
this.overtime=overtime;
}
/**
*@
*/
publicvoidsetSleeptime(longsleeptime){
this.sleeptime=sleeptime;
}
/*(non-Javadoc)
*@seecom.iol.common.util.concurrent.locks.IRedisLockArithmetic#lock(java.lang.String,java.lang.Long)
*/
@Override
publicbooleanlock(Stringkey){
while(true){
//當前加鎖時間
currentLockTime=System.currentTimeMillis();
if(redisComp.setIfAbsent(key,currentLockTime)){
//獲取鎖成功
logger.debug("直接獲取鎖{key:{},currentLockTime:{}}",key,currentLockTime);
returntrue;
}else{
//其他線程佔用了鎖
logger.debug("檢測到鎖被佔用{key:{},currentLockTime:{}}",key,currentLockTime);
LongotherLockTime=redisComp.get(key);
if(otherLockTime==null){
//其他系統釋放了鎖
//立刻重新嘗試加鎖
logger.debug("檢測到鎖被釋放{key:{},currentLockTime:{}}",key,currentLockTime);
continue;
}else{
if(currentLockTime-otherLockTime>=overtime){
//鎖超時
//嘗試更新鎖
logger.debug("檢測到鎖超時{key:{},currentLockTime:{},otherLockTime:{}}",key,currentLockTime,otherLockTime);
LongotherLockTime2=redisComp.getAndSet(key,currentLockTime);
if(otherLockTime2==null||otherLockTime.equals(otherLockTime2)){
logger.debug("獲取到超時鎖{key:{},currentLockTime:{},otherLockTime:{},otherLockTime2:{}}",key,currentLockTime,otherLockTime,otherLockTime2);
returntrue;
}else{
sleep();
//重新嘗試加鎖
logger.debug("重新嘗試加鎖{key:{},currentLockTime:{}}",key,currentLockTime);
continue;
}
}else{
//鎖未超時
sleep();
//重新嘗試加鎖
logger.debug("重新嘗試加鎖{key:{},currentLockTime:{}}",key,currentLockTime);
continue;
}
}
}
}
}
/*(non-Javadoc)
*@seecom.iol.common.util.concurrent.locks.IRedisLockArithmetic#unLock(java.lang.String)
*/
@Override
publicbooleanunLock(Stringkey){
logger.debug("解鎖{key:{}}",key);
redisComp.delete(key);
returntrue;
}
/**
*休眠<br/>
*@paramsleeptime
*/
privatevoidsleep(){
try{
Thread.sleep(sleeptime);
}catch(InterruptedExceptione){
thrownewLockException("線程異常中斷",e);
}
}
}
G. java多線程『鎖』,是用什麼鎖的,有方法
synchronized關鍵字可以讓你對一個對象加鎖,
比如synchronized(this);表示對當前類對象加鎖,這是一個排他所,即只有一個線程可以訪問被synchronized的對象