【多線程】synchronized與Lock的區別
相同點
都是用來保護資源線程安全的
都可以保證可見性
可見性大致可以這樣理解,線程A的加解鎖的過程會對B線程完全可見,也就是說,線程A的加鎖和解鎖當時的鎖持有的狀態,線程B是可以獲取到的,這也就體現到了hanppens-before針對synchronized的一個原則。

對于Lock而言,他也是可以保證線程的可見性,例如下面示例的流程

關于可見性,可以詳細了解Java內存模型的知識。
都擁有可重入的特點
關于可重入鎖,他表示的是一個線程A他獲取到了B鎖,如果線程A在運行的過程中想要再獲取B鎖的同時,不需要B鎖再釋放鎖資源就能夠獲取到,那么他就是一個可重入的鎖,這個synchronized與ReentrantLock都具有相同的特點。
關于可重入鎖的知識可以看一下【多線程】鎖的七大分類
不同點
用法區別
Lock的鎖具有靈活性,他可以在A先加鎖,B再加鎖的時候,實現A先解鎖,B再解鎖。這里的解鎖順序可以完全由我們自行控制。
lock1.lock();
lock2.lock();
...
lock1.unlock();
lock2.unlock();
synchronized就無法做到這一點,原因是由于synchronized加鎖和解鎖的順序完全是由JVM生成的代碼來實現的,屬于隱式加鎖。所以他的加解鎖的順序一定是要符合后加鎖先解鎖的原則。
synchronized(obj1){
synchronized(obj2){
...
}
}
線程鎖的共享性
synchronized 鎖只能同時被一個線程擁有,但是 Lock 鎖沒有這個限制。
這個原因是因為synchronized他是內置鎖,由JVM實現獲取鎖和釋放鎖的原理,我們無法通過代碼控制,Lock則可以根據實現不同,有不同的原理,例如ReentrantLock內部是通過AQS來獲取和釋放鎖的。
線程鎖的公平性
ReentrantLock可以根據Lock等實現類設置公平或非公平,synchronized則無法設置。
性能區別
synchronized在Java5之前性能是非常低的,在Java的研發團隊不斷的優化和迭代之后,synchronized鎖的性不比Lock鎖的性能差,因為他優化了很多,比如自適應自旋,鎖消除,鎖粗化,輕量級鎖,偏向鎖等。
適用場景
在我們平時日常編寫代碼中,能不用就最好不用Lock和synchronized鎖,因為在許多情況下你可以使用java.util.concurrent包中的機制,他中間就包括了很多鎖的處理,也是推薦優先使用工具來來加解鎖。
如果你需要使用一些特鎖的功能,比如設置公平性或者控制解鎖的順序,那么就可以使用Lock來加解鎖,但是如果你用不到Lock的特性,則建議直接使用synchronized,應為這樣可以減少代碼的數量,并且還會減少出錯的概率,因為使用Lock來加鎖,就必須finally的去解鎖,如果忘記,代碼就會出現很大的問題,相比之下,用synchronized會跟安全。

浙公網安備 33010602011771號