一、ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候
线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定,
若是使用 synchronized ,若是A不释放,B将一直等下去,不能被中断
若是 使用ReentrantLock,若是A不释放,可使B在等待了足够长的时间之后,中断等待,而干别的事情
ReentrantLock获取锁定与三种方式:
a) lock(), 若是获取了锁当即返回,若是别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁
b) tryLock(), 若是获取了锁当即返回true,若是别的线程正持有锁,当即返回false;
c)tryLock(long timeout,TimeUnit unit), 若是获取了锁定当即返回true,若是别的线程正持有锁,会等待参数给定的时间,在等待的过程当中,若是获取了锁定,就返回true,若是等待超时,返回false;
d) lockInterruptibly:若是获取了锁定当即返回,若是没有获取锁定,当前线程处于休眠状态,直到或者锁定,或者当前线程被别的线程中断
二、synchronized是在JVM层面上实现的,不但能够经过一些监控工具监控synchronized的锁定,并且在代码执行时出现异常,JVM会自动释放锁定,可是使用Lock则不行,lock是经过代码实现的,要保证锁定必定会被释放,就必须将unLock()放到finally{}中
三、在资源竞争不是很激烈的状况下,Synchronized的性能要优于ReetrantLock,可是在资源竞争很激烈的状况下,Synchronized的性能会降低几十倍,可是ReetrantLock的性能能维持常态;java
5.0的多线程任务包对于同步的性能方面有了很大的改进,在原有synchronized关键字的基础上,又增长了ReentrantLock,以及各类Atomic类。了解其性能的优劣程度,有助与咱们在特定的情形下作出正确的选择。程序员
整体的结论先摆出来:安全
synchronized:
在资源竞争不是很激烈的状况下,偶尔会有同步的情形下,synchronized是很合适的。缘由在于,编译程序一般会尽量的进行优化synchronize,另外可读性很是好,无论用没用过5.0多线程包的程序员都能理解。多线程
ReentrantLock:
ReentrantLock提供了多样化的同步,好比有时间限制的同步,能够被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性能稍微比synchronized差点点。可是当同步很是激烈的时候,synchronized的性能一会儿能降低好几十倍。而ReentrantLock确还能维持常态。并发
Atomic:
和上面的相似,不激烈状况下,性能比synchronized略逊,而激烈的时候,也能维持常态。激烈的时候,Atomic的性能会优于ReentrantLock一倍左右。可是其有一个缺点,就是只能同步一个值,一段代码中只能出现一个Atomic的变量,多于一个同步无效。由于他不能在多个Atomic之间同步。dom
因此,咱们写同步的时候,优先考虑synchronized,若是有特殊须要,再进一步优化。ReentrantLock和Atomic若是用的很差,不只不能提升性能,还可能带来灾难。ide
先贴测试结果:再贴代码(Atomic测试代码不许确,一个同步中只能有1个Actomic,这里用了2个,可是这里的测试只看速度)
==========================
round:100000 thread:5
Sync = 35301694
Lock = 56255753
Atom = 43467535
==========================
round:200000 thread:10
Sync = 110514604
Lock = 204235455
Atom = 170535361
==========================
round:300000 thread:15
Sync = 253123791
Lock = 448577123
Atom = 362797227
==========================
round:400000 thread:20
Sync = 16562148262
Lock = 846454786
Atom = 667947183
==========================
round:500000 thread:25
Sync = 26932301731
Lock = 1273354016
Atom = 982564544工具
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
|
package
test.thread;
import
static
java.lang.System.out;
import
java.util.Random;
import
java.util.concurrent.BrokenBarrierException;
import
java.util.concurrent.CyclicBarrier;
import
java.util.concurrent.ExecutorService;
import
java.util.concurrent.Executors;
import
java.util.concurrent.atomic.AtomicInteger;
import
java.util.concurrent.atomic.AtomicLong;
import
java.util.concurrent.locks.ReentrantLock;
public
class
TestSyncMethods {
public
static
void
test(
int
round,
int
threadNum,CyclicBarrier cyclicBarrier){
new
SyncTest(
"Sync"
,round,threadNum,cyclicBarrier).testTime();
new
LockTest(
"Lock"
,round,threadNum,cyclicBarrier).testTime();
new
AtomicTest(
"Atom"
,round,threadNum,cyclicBarrier).testTime();
}
public
static
void
main(String args[]){
for
(
int
i=
0
;i<
5
;i++){
int
round=
100000
*(i+
1
);
int
threadNum=
5
*(i+
1
);
CyclicBarrier cb=
new
CyclicBarrier(threadNum*
2
+
1
);
out.println(
"=========================="
);
out.println(
"round:"
+round+
" thread:"
+threadNum);
test(round,threadNum,cb);
}
}
}
class
SyncTest
extends
TestTemplate{
public
SyncTest(String _id,
int
_round,
int
_threadNum,CyclicBarrier _cb){
super
( _id, _round, _threadNum, _cb);
}
@Override
/**
* synchronized关键字不在方法签名里面,因此不涉及重载问题
*/
synchronized
long
getValue() {
return
super
.countValue;
}
@Override
synchronized
void
sumValue() {
super
.countValue+=preInit[index++%round];
}
}
class
LockTest
extends
TestTemplate{
ReentrantLock lock=
new
ReentrantLock();
public
LockTest(String _id,
int
_round,
int
_threadNum,CyclicBarrier _cb){
super
( _id, _round, _threadNum, _cb);
}
/**
* synchronized关键字不在方法签名里面,因此不涉及重载问题
*/
@Override
long
getValue() {
try
{
lock.lock();
return
super
.countValue;
}
finally
{
lock.unlock();
}
}
@Override
void
sumValue() {
try
{
lock.lock();
super
.countValue+=preInit[index++%round];
}
finally
{
lock.unlock();
}
}
}
class
AtomicTest
extends
TestTemplate{
public
AtomicTest(String _id,
int
_round,
int
_threadNum,CyclicBarrier _cb){
super
( _id, _round, _threadNum, _cb);
}
@Override
/**
* synchronized关键字不在方法签名里面,因此不涉及重载问题
*/
long
getValue() {
return
super
.countValueAtmoic.get();
}
@Override
void
sumValue() {
super
.countValueAtmoic.addAndGet(
super
.preInit[indexAtomic.get()%round]);
}
}
abstract
class
TestTemplate{
private
String id;
protected
int
round;
private
int
threadNum;
protected
long
countValue;
protected
AtomicLong countValueAtmoic=
new
AtomicLong(
0
);
protected
int
[] preInit;
protected
int
index;
protected
AtomicInteger indexAtomic=
new
AtomicInteger(
0
);
Random r=
new
Random(
47
);
//任务栅栏,同批任务,先到达wait的任务挂起,一直等到所有任务到达制定的wait地点后,才能所有唤醒,继续执行
private
CyclicBarrier cb;
public
TestTemplate(String _id,
int
_round,
int
_threadNum,CyclicBarrier _cb){
this
.id=_id;
this
.round=_round;
this
.threadNum=_threadNum;
cb=_cb;
preInit=
new
int
[round];
for
(
int
i=
0
;i<preInit.length;i++){
preInit[i]=r.nextInt(
100
);
}
}
abstract
void
sumValue();
/*
* 对long的操做是非原子的,原子操做只针对32位
* long是64位,底层操做的时候分2个32位读写,所以不是线程安全
*/
abstract
long
getValue();
public
void
testTime(){
ExecutorService se=Executors.newCachedThreadPool();
long
start=System.nanoTime();
//同时开启2*ThreadNum个数的读写线程
for
(
int
i=
0
;i<threadNum;i++){
se.execute(
new
Runnable(){
public
void
run() {
for
(
int
i=
0
;i<round;i++){
sumValue();
}
//每一个线程执行完同步方法后就等待
try
{
cb.await();
}
catch
(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch
(BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
se.execute(
new
Runnable(){
public
void
run() {
getValue();
try
{
//每一个线程执行完同步方法后就等待
cb.await();
}
catch
(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch
(BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
try
{
//当前统计线程也wait,因此CyclicBarrier的初始值是threadNum*2+1
cb.await();
}
catch
(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch
(BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//全部线程执行完成以后,才会跑到这一步
long
duration=System.nanoTime()-start;
out.println(id+
" = "
+duration);
}
}
|
摘自:性能
http://houlinyan.iteye.com/blog/1112535测试
http://zzhonghe.iteye.com/blog/826162