Synchronized和Lock感悟

synchronized 修飾方法時 表示同一個對象在不同的線程中 表現爲同步隊列
如果實例化不同的對象 那麼synchronized就不會出現同步效果了

對象的鎖
所有對象都自動含有單一的鎖。
JVM負責跟蹤對象被加鎖的次數。如果一個對象被解鎖,其計數變爲0。在任務(線程)第一次給對象加鎖的時候,計數變爲1。每當這個相同的任務(線程)在此對象上獲得鎖時,計數會遞增。
只有首先獲得鎖的任務(線程)才能繼續獲取該對象上的多個鎖。
每當任務離開一個synchronized方法,計數遞減,當計數爲0的時候,鎖被完全釋放,此時別的任務就可以使用此資源。

synchronized同步塊
同步到單一對象鎖
當使用同步塊時,如果方法下的同步塊都同步到一個對象上的鎖,則所有的任務(線程)只能互斥的進入這些同步塊。
Resource1.java演示了三個線程(包括main線程)試圖進入某個類的三個不同的方法的同步塊中,雖然這些同步塊處在不同的方法中,但由於是同步到同一個對象(當前對象 synchronized (this)),所以對它們的方法依然是互斥的。

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(“liaomin”);
u.setUserPassword(“liaomin”);
Test.add(u);

如果在線程2中

Test tes1t=new Test();
User u1=new User();
u1.setUserName(“huqun”);
u1.setUserPassword(“huqun”);
Tes1t.add(u1);

那麼 現在線程1 和線程2同時啓動 如果對象new的不是同一個Test
那麼出現線程交叉的話 那麼插入數據庫中的數據就是相同的
因爲你的user變量時靜態的 你給他賦值第一次 假如還沒有save的時候
另外一個線程改變了user的值 那麼第一個線程插入時也就是第二次賦予的值了
所以要實現同步 那麼可以改方法爲靜態的就能達到同步的效果了
修改如下

Public static synchronized void add(User u)
{
     user=u;
     Dao.save(user)
}

修改爲static的方法是存在於堆中

是全局方法 針對於所有實例化與未 實例化的對象只存在一個 所以會出現同步隊列
當然不用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多少個對象都會是線程同步的

相當於

Public static synchronized void add(User u)
{
    user=u;
    Dao.save(user)
}

同時 lock性能上高於synchronized

只是lock需要手動關閉
ps:
主要相同點:lock能完成synchronized所實現的所有功能
主要不同點:lock有比synchronized更精確的線程語義和更好的性能.synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放,並且必須在finally從句中釋放.

發佈了31 篇原創文章 · 獲贊 23 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章