鎖是控制多個執行緒對共享資源進行存取的工具。通常,鎖提供了對共享資源的獨佔存取。一次只能有一個執行緒獲得鎖,對共享資源的所有存取都需要先獲得鎖。不過,某些鎖可能允許對共享資源並發訪問,如 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(); } } } }
更多Java多執行緒程式設計之Lock用法實例相關文章請關注PHP中文網!