深入Synchronized和java.util.concurrent.locks.Lock的區(qū)別詳解
更新時(shí)間:2013年06月04日 15:27:40 作者:
本篇文章是對(duì)Synchronized和java.util.concurrent.locks.Lock的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
主要相同點(diǎn):Lock能完成Synchronized所實(shí)現(xiàn)的所有功能。
主要不同點(diǎn):Lock有比Synchronized更精確的線程予以和更好的性能。Synchronized會(huì)自動(dòng)釋放鎖,但是Lock一定要求程序員手工釋放,并且必須在finally從句中釋放。
synchronized 修飾方法時(shí) 表示同一個(gè)對(duì)象在不同的線程中 表現(xiàn)為同步隊(duì)列
如果實(shí)例化不同的對(duì)象 那么synchronized就不會(huì)出現(xiàn)同步效果了。
1.對(duì)象的鎖
所有對(duì)象都自動(dòng)含有單一的鎖。
JVM負(fù)責(zé)跟蹤對(duì)象被加鎖的次數(shù)。如果一個(gè)對(duì)象被解鎖,其計(jì)數(shù)變?yōu)?。在任務(wù)(線程)第一次給對(duì)象加鎖的時(shí)候,計(jì)數(shù)變?yōu)?。每當(dāng)這個(gè)相同的任務(wù)(線程)在此對(duì)象上獲得鎖時(shí),計(jì)數(shù)會(huì)遞增。
只有首先獲得鎖的任務(wù)(線程)才能繼續(xù)獲取該對(duì)象上的多個(gè)鎖。
每當(dāng)任務(wù)離開一個(gè)synchronized方法,計(jì)數(shù)遞減,當(dāng)計(jì)數(shù)為0的時(shí)候,鎖被完全釋放,此時(shí)別的任務(wù)就可以使用此資源。
2.synchronized同步塊
2.1同步到單一對(duì)象鎖
當(dāng)使用同步塊時(shí),如果方法下的同步塊都同步到一個(gè)對(duì)象上的鎖,則所有的任務(wù)(線程)只能互斥的進(jìn)入這些同步塊。
Resource1.java演示了三個(gè)線程(包括main線程)試圖進(jìn)入某個(gè)類的三個(gè)不同的方法的同步塊中,雖然這些同步塊處在不同的方法中,但由于是同步到同一個(gè)對(duì)象(當(dāng)前對(duì)象 synchronized (this)),所以對(duì)它們的方法依然是互斥的。
比如
Class Test
{
public static User user=null;
Public synchronized void add(User u)
{
user=u;
Dao.save(user)
}
}
如果在線程1中
Test test=new Test();
User u=new User();
u.setUserName(“l(fā)iaomin”);
u.setUserPassword(“l(fā)iaomin”);
Test.add(u);
如果在線程2中
Test tes1t=new Test();
User u1=new User();
u1.setUserName(“huqun”);
u1.setUserPassword(“huqun”);
Tes1t.add(u1);
那么 現(xiàn)在線程1 和線程2同時(shí)啟動(dòng) 如果對(duì)象new的不是同一個(gè)Test
那么出現(xiàn)線程交叉的話 那么插入數(shù)據(jù)庫中的數(shù)據(jù)就是相同的
因?yàn)槟愕膗ser變量時(shí)靜態(tài)的 你給他賦值第一次 假如還沒有save的時(shí)候
另外一個(gè)線程改變了user的值 那么第一個(gè)線程插入時(shí)也就是第二次賦予的值了
所以要實(shí)現(xiàn)同步 那么可以改方法為靜態(tài)的就能達(dá)到同步的效果了
修改如下
Public static synchronized void add(User u)
{
user=u;
Dao.save(user)
}
修改為static的方法是存在于堆中
是全局方法 針對(duì)于所有實(shí)例化與未 實(shí)例化的對(duì)象只存在一個(gè) 所以會(huì)出現(xiàn)同步隊(duì)列
當(dāng)然不用static 也可以 那就用lock
Class Test
{
public static User user=null;
Lock lock=new ReentrantLock();
Public void add(User u)
{
lock.lock();
user=u;
Dao.save(user);
lock.unlock();
}
}
這樣無論你new多少個(gè)對(duì)象都會(huì)是線程同步的
相當(dāng)于
Public static synchronized void add(User u)
{
user=u;
Dao.save(user)
}
同時(shí) lock性能上高于synchronized
只是lock需要手動(dòng)關(guān)閉
主要不同點(diǎn):Lock有比Synchronized更精確的線程予以和更好的性能。Synchronized會(huì)自動(dòng)釋放鎖,但是Lock一定要求程序員手工釋放,并且必須在finally從句中釋放。
synchronized 修飾方法時(shí) 表示同一個(gè)對(duì)象在不同的線程中 表現(xiàn)為同步隊(duì)列
如果實(shí)例化不同的對(duì)象 那么synchronized就不會(huì)出現(xiàn)同步效果了。
1.對(duì)象的鎖
所有對(duì)象都自動(dòng)含有單一的鎖。
JVM負(fù)責(zé)跟蹤對(duì)象被加鎖的次數(shù)。如果一個(gè)對(duì)象被解鎖,其計(jì)數(shù)變?yōu)?。在任務(wù)(線程)第一次給對(duì)象加鎖的時(shí)候,計(jì)數(shù)變?yōu)?。每當(dāng)這個(gè)相同的任務(wù)(線程)在此對(duì)象上獲得鎖時(shí),計(jì)數(shù)會(huì)遞增。
只有首先獲得鎖的任務(wù)(線程)才能繼續(xù)獲取該對(duì)象上的多個(gè)鎖。
每當(dāng)任務(wù)離開一個(gè)synchronized方法,計(jì)數(shù)遞減,當(dāng)計(jì)數(shù)為0的時(shí)候,鎖被完全釋放,此時(shí)別的任務(wù)就可以使用此資源。
2.synchronized同步塊
2.1同步到單一對(duì)象鎖
當(dāng)使用同步塊時(shí),如果方法下的同步塊都同步到一個(gè)對(duì)象上的鎖,則所有的任務(wù)(線程)只能互斥的進(jìn)入這些同步塊。
Resource1.java演示了三個(gè)線程(包括main線程)試圖進(jìn)入某個(gè)類的三個(gè)不同的方法的同步塊中,雖然這些同步塊處在不同的方法中,但由于是同步到同一個(gè)對(duì)象(當(dāng)前對(duì)象 synchronized (this)),所以對(duì)它們的方法依然是互斥的。
比如
復(fù)制代碼 代碼如下:
Class Test
{
public static User user=null;
Public synchronized void add(User u)
{
user=u;
Dao.save(user)
}
}
如果在線程1中
復(fù)制代碼 代碼如下:
Test test=new Test();
User u=new User();
u.setUserName(“l(fā)iaomin”);
u.setUserPassword(“l(fā)iaomin”);
Test.add(u);
如果在線程2中
復(fù)制代碼 代碼如下:
Test tes1t=new Test();
User u1=new User();
u1.setUserName(“huqun”);
u1.setUserPassword(“huqun”);
Tes1t.add(u1);
那么 現(xiàn)在線程1 和線程2同時(shí)啟動(dòng) 如果對(duì)象new的不是同一個(gè)Test
那么出現(xiàn)線程交叉的話 那么插入數(shù)據(jù)庫中的數(shù)據(jù)就是相同的
因?yàn)槟愕膗ser變量時(shí)靜態(tài)的 你給他賦值第一次 假如還沒有save的時(shí)候
另外一個(gè)線程改變了user的值 那么第一個(gè)線程插入時(shí)也就是第二次賦予的值了
所以要實(shí)現(xiàn)同步 那么可以改方法為靜態(tài)的就能達(dá)到同步的效果了
修改如下
復(fù)制代碼 代碼如下:
Public static synchronized void add(User u)
{
user=u;
Dao.save(user)
}
修改為static的方法是存在于堆中
是全局方法 針對(duì)于所有實(shí)例化與未 實(shí)例化的對(duì)象只存在一個(gè) 所以會(huì)出現(xiàn)同步隊(duì)列
當(dāng)然不用static 也可以 那就用lock
復(fù)制代碼 代碼如下:
Class Test
{
public static User user=null;
Lock lock=new ReentrantLock();
Public void add(User u)
{
lock.lock();
user=u;
Dao.save(user);
lock.unlock();
}
}
這樣無論你new多少個(gè)對(duì)象都會(huì)是線程同步的
相當(dāng)于
復(fù)制代碼 代碼如下:
Public static synchronized void add(User u)
{
user=u;
Dao.save(user)
}
同時(shí) lock性能上高于synchronized
只是lock需要手動(dòng)關(guān)閉
您可能感興趣的文章:
相關(guān)文章
Spring Security自定義認(rèn)證器的實(shí)現(xiàn)代碼
這篇文章主要介紹了Spring Security自定義認(rèn)證器的實(shí)現(xiàn)代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06詳解基于java的Socket聊天程序——初始設(shè)計(jì)(附demo)
本篇文章主要介紹了Socket聊天程序——初始設(shè)計(jì)(附demo),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-12-12java 抓取網(wǎng)頁內(nèi)容實(shí)現(xiàn)代碼
這篇文章主要介紹了java 抓取網(wǎng)頁內(nèi)容實(shí)現(xiàn)代碼,需要的朋友可以參考下2014-02-02如何實(shí)現(xiàn)自定義SpringBoot的Starter組件
這篇文章主要介紹了實(shí)現(xiàn)自定義SpringBoot的Starter組件的示例代碼,想要自定義starter組件,首先要了解springboot是如何加載starter的,也就是springboot的自動(dòng)裝配機(jī)制原理,本文結(jié)合示例代碼詳細(xì)講解,需要的朋友可以參考下2023-02-02詳解Java去除json數(shù)據(jù)中的null空值問題
這篇文章主要介紹了詳解Java去除json數(shù)據(jù)中的null空值問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08