鎖是控制多個線程對共享資源進行訪問的工具。通常,鎖提供了對共享資源的獨占訪問。一次只能有一個線程獲得鎖,對共享資源的所有訪問都需要首先獲得鎖。不過,某些鎖可能允許對共享資源並發訪問,如ReadWriteLock(維護了一對相關的鎖,一個用於只讀操作,另一個用於寫入操作) 的讀寫鎖。
1、Lock提供了無條件的、可輪詢的、定時的、可中斷的鎖獲取操作,所有加鎖和解鎖的方法都是顯式的。
public interface Lock{ void lock(); //加鎖//優先考慮響應中斷,而不是響應鎖定的普通獲取或重入獲取void lockInterruptibly() throws InterruptedException; boolean tryLock(); //可定時和可輪詢的鎖獲取模式boolean tryLock(long timeout,TimeUnit unit) throws InterruptedException; void unlock(); //解鎖Condition newCondition();}
2、ReentrantLock實現了lock接口,跟synchronized相比,ReentrantLock為處理不可用的鎖提供了更多靈活性。
3、使用lock接口的規範形式要求在finally塊中釋放鎖lock.unlock()。如果鎖守護的代碼在try塊之外拋出了異常,它將永遠不會被釋放。
以下模擬Lock用法:假設有兩個線程(A線程、B線程)去調用print(String name)方法,A線程負責打印'zhangsan'字符串,B線程負責打印'lisi'字符串。
1、當沒有為print(String name)方法加上鎖時,則會產生A線程還沒有執行完畢,B線程已開始執行,那麼打印出來的name就會出現如下問題。
2、當為print(String name)方法加上鎖時,則會產生A執行完畢後,B線程才執行print(String name)方法,達到互斥或者說同步效果。
package com.ljq.test.thread; import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock; /** * 用Lock替代synchronized * * @author Administrator * */public class LockTest { public static void main(String[] args) { new LockTest().init(); } private void init() { final Outputer outputer = new Outputer(); //A線程new Thread(new Runnable() { @ Override public void run() { while (true) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } outputer.output("zhangsan"); } } }).start (); //B線程new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } outputer.output("lisi"); } } }).start(); } static class Outputer { Lock lock = new ReentrantLock(); /** * 打印字符* * @param name */ public void output(String name) { int len = name.length(); lock.lock(); try { for (int i = 0; i < len; i++) { System.out.print(name.charAt(i)); } System .out.println(); } finally { lock.unlock(); } } }}