引言
在多線(xiàn)程中,為了使線(xiàn)程安全,我們經(jīng)常會(huì )使用synchronized和Lock進(jìn)行代碼同步和加鎖,但是具體兩者有什么區別,什么場(chǎng)景下適合用什么可能還不大清楚,主要的區別大致如下:
區別
1、synchronized是java關(guān)鍵字,而Lock是java中的一個(gè)接口
2、synchronized會(huì )自動(dòng)釋放鎖,而Lock必須手動(dòng)釋放鎖
3、synchronized是不可中斷的,Lock可以中斷也可以不中斷
4、通過(guò)Lock可以知道線(xiàn)程有沒(méi)有拿到鎖,而synchronized不能
5、synchronized能鎖住方法和代碼塊,而Lock只能鎖住代碼塊
6、Lock可以使用讀鎖提高多線(xiàn)程讀效率
7、synchronized是非公平鎖,ReentranLock可以控制是否公平鎖
1 Object objlock = new Object(); 2 synchronized(objlock) { //加鎖 3 //... 邏輯 ... 4 } //解鎖 5 6 7 Lock lock = new ReentrantLock(); 8 lock.lock(); //加鎖 9 try { 10 //... 邏輯 ... 11 } finally { 12 lock.unlock(); //解鎖 13 }
從Lock接口中我們可以看到主要有5個(gè)方法,這些方法的功能從注釋中可以看出:
1 lock():獲取鎖,如果鎖被暫用則一直等待 2 unlock():釋放鎖 3 tryLock(): 注意返回類(lèi)型是boolean,如果獲取鎖的時(shí)候鎖被占用就返回false,否則返回true 4 tryLock(long time, TimeUnit unit):比起tryLock()就是給了一個(gè)時(shí)間期限,保證等待參數時(shí)間 5 lockInterruptibly():用該鎖的獲得方式,如果線(xiàn)程在獲取鎖的階段進(jìn)入了等待,那么可以中斷此線(xiàn)程,先去做別的事 通過(guò) 以上的解釋?zhuān)笾驴梢越忉屧谏蟼€(gè)部分中“鎖類(lèi)型(lockInterruptibly())”,“鎖狀態(tài)(tryLock())”等問(wèn)題,還有就是前面子所獲取的過(guò)程我所寫(xiě)的“大致就是可以嘗試獲得鎖,線(xiàn)程可以不會(huì )一直等待”用了“可以”的原因。
lock():
1 public class LockTest { 2 private Lock lock = new ReentrantLock(); 3 4 private void method(Thread thread) { 5 lock.lock(); 6 try { 7 System.out.println(thread.getName() + " has gotten the lock!"); 8 } catch (Exception e) { 9 e.printStackTrace(); 10 } finally { 11 System.out.println(thread.getName() + " has unlocked the lock!"); 12 lock.unlock(); 13 } 14 } 15 16 public static void main(String[] args) { 17 final LockTest test = new LockTest(); 18 19 Thread t1 = new Thread(new Runnable() { 20 @Override 21 public void run() { 22 test.method(Thread.currentThread()); 23 } 24 }, "t1"); 25 Thread t2 = new Thread(new Runnable() { 26 @Override 27 public void run() { 28 test.method(Thread.currentThread()); 29 } 30 }, "t2"); 31 t1.start(); 32 t2.start(); 33 } 34 35 }
運行結果:
t1 has gotten the lock! t1 has unlocked the lock! t2 has gotten the lock! t2 has unlocked the lock!
tryLock():
1 public class LockTest { 2 private Lock lock = new ReentrantLock(); 3 4 private void method(Thread thread) { 5 6 if (lock.tryLock()) { 7 lock.lock(); 8 try { 9 System.out.println(thread.getName() + " has gotten the lock!"); 10 } catch (Exception e) { 11 e.printStackTrace(); 12 } finally { 13 System.out.println(thread.getName() + " has unlocked the lock!"); 14 lock.unlock(); 15 } 16 } else { 17 System.out.println("I'm "+thread.getName()+". Someone has gotten the lock!"); 18 } 19 } 20 21 public static void main(String[] args) { 22 LockTest test = new LockTest(); 23 24 Thread t1 = new Thread(() -> test.method(Thread.currentThread()), "t1"); 25 Thread t2 = new Thread(new Runnable() { 26 @Override 27 public void run() { 28 test.method(Thread.currentThread()); 29 } 30 }, "t2"); 31 t1.start(); 32 t2.start(); 33 } 34 }
運行結果:
t1 has gotten the lock! t1 has unlocked the lock! I'm t2. Someone has gotten the lock!
看到這里相信大家也都會(huì )使用如何使用Lock了吧,關(guān)于tryLock(long time, TimeUnit unit)和lockInterruptibly()不再贅述。前者主要存在一個(gè)等待時(shí)間,在測試代碼中寫(xiě)入一個(gè)等待時(shí)間,后者主要是等待中斷,會(huì )拋出一個(gè)中斷異常,常用度不高,喜歡探究可以自己深入研究。
聯(lián)系客服