鎖是控制多個(gè)線程對(duì)共享資源進(jìn)行訪問(wèn)的工具。通常,鎖提供了對(duì)共享資源的獨(dú)占訪問(wèn)。一次只能有一個(gè)線程獲得鎖,對(duì)共享資源的所有訪問(wèn)都需要首先獲得鎖。不過(guò),某些鎖可能允許對(duì)共享資源并發(fā)訪問(wèn),如 ReadWriteLock(維護(hù)了一對(duì)相關(guān)的鎖,一個(gè)用于只讀操作,另一個(gè)用于寫入操作) 的讀寫鎖。
1、Lock提供了無(wú)條件的、可輪詢的、定時(shí)的、可中斷的鎖獲取操作,所有加鎖和解鎖的方法都是顯式的。
1
2
3
4
5
6
7
8
9
|
public interface Lock{ void lock(); //加鎖 //優(yōu)先考慮響應(yīng)中斷,而不是響應(yīng)鎖定的普通獲取或重入獲取 void lockInterruptibly() throws InterruptedException; boolean tryLock(); //可定時(shí)和可輪詢的鎖獲取模式 boolean tryLock( long timeout,TimeUnit unit) throws InterruptedException; void unlock(); //解鎖 Condition newCondition(); } |
2、ReentrantLock實(shí)現(xiàn)了lock接口,跟synchronized相比,ReentrantLock為處理不可用的鎖提供了更多靈活性。
3、使用lock接口的規(guī)范形式要求在finally塊中釋放鎖lock.unlock()。如果鎖守護(hù)的代碼在try塊之外拋出了異常,它將永遠(yuǎn)不會(huì)被釋放。
以下模擬Lock用法:假設(shè)有兩個(gè)線程(A線程、B線程)去調(diào)用print(String name)方法,A線程負(fù)責(zé)打印'zhangsan'字符串,B線程負(fù)責(zé)打印'lisi'字符串。
1、當(dāng)沒(méi)有為print(String name)方法加上鎖時(shí),則會(huì)產(chǎn)生A線程還沒(méi)有執(zhí)行完畢,B線程已開(kāi)始執(zhí)行,那么打印出來(lái)的name就會(huì)出現(xiàn)如下問(wèn)題。
2、當(dāng)為print(String name)方法加上鎖時(shí),則會(huì)產(chǎn)生A執(zhí)行完畢后,B線程才執(zhí)行print(String name)方法,達(dá)到互斥或者說(shuō)同步效果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
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(); } } } } |