在Java5 诞生之前,Java线程同步和协助只能使用synchronized锁机制,这种锁机制由JVM直接提供实现,所以经常又称内部锁,也称作对象监视器,由于这种锁有性能缺陷而且灵活不足,所以牛人在Java5添加了Lock接口及相关实现,为Java多线程同步与协作提供了另一种选择,当然,后来者不管功能还是性能都比前者优秀,以致有人倡导全部使用Lock抛弃synchronized。有了竞争就会迫使进步,果然Java 6对内部锁进行优化,性能大幅度提升,大部分情况下与Lock可以相媲美(但非公平竞争情况下Lock还是存在性能优势)而且JCP专家组提倡简单正常情况下使用synchronized内部锁,并称将来内部锁还会继续进行优化,所以现在synchronized还是广为使用。然而这只是性能方面,在功能方面Lock提供了更多的灵活性,如轮询锁、定时锁、可中断的锁获取、非块结构的加解锁等,并且在Java5以后的并发包中广为使用,所以学习研究Lock还是必须的。
1
2
3
4
|
public
interface
Lock {
void
lock();
void
unlock();
}
|
对于简单线程同步,Lock使用lock()方法请求并加锁,需要自己使用unlock()方法释放锁,并不需要限定代码范围,如果忘记会造成死锁,这是灵活性带来的负面影响,所以使用时都会增加try{...}finally{lock.unlock()},以保证锁的释放;synchronized在代码块范围外会自动释放锁,一开始就定义好锁定的代码范围,比较死板但可靠,另外synchronized经常用于修饰类成员方法,线程调用这种方法前需要先获得对应的锁,这种使用方式很顺手,简单明了,Lock没有这种语法。
Lock和synchronized对线程同步操作示例:
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
76
77
78
79
80
81
|
import
java.util.concurrent.TimeUnit;
import
java.util.concurrent.locks.Lock;
import
java.util.concurrent.locks.ReentrantLock;
public
class
TestLock {
private
int
mCount;
private
Lock mLock;
public
TestLock(){
this
.mCount =
0
;
this
.mLock =
new
ReentrantLock();
}
public
static
void
main(String[] args)
throws
InterruptedException {
TestLock testLock =
new
TestLock();
for
(
int
i=
0
; i<
2
; i++){
new
Thread(testLock.
new
SThread()).start();
}
TimeUnit.SECONDS.sleep(
3
);
for
(
int
i=
0
; i<
2
; i++){
new
Thread(testLock.
new
LThread()).start();
}
}
private
void
increaseCount() {
mCount++;
System.out.println(Thread.currentThread().getName() +
" do lock, count: "
+ mCount);
}
private
void
decreaseCount() {
mCount--;
System.out.println(Thread.currentThread().getName() +
" do unlock, count: "
+ mCount);
}
private
void
doCountWithLSync() {
mLock.lock();
try
{
increaseCount();
mLock.lock();
//re-enter
try
{
increaseCount();
}
finally
{
mLock.unlock();
decreaseCount();
}
}
finally
{
mLock.unlock();
decreaseCount();
}
}
private
void
doCountWithSSync() {
synchronized
(
this
){
increaseCount();
synchronized
(
this
){
//re-enter
increaseCount();
}
decreaseCount();
}
decreaseCount();
}
private
class
LThread
implements
Runnable{
public
void
run(){
doCountWithLSync();
}
}
private
class
SThread
implements
Runnable{
public
void
run(){
doCountWithSSync();
}
}
}
|
本文转自sarchitect 51CTO博客,原文链接:http://blog.51cto.com/stevex/1300164,如需转载请自行联系原作者