1使用案例
public class ReenterLock implements Runnable{
public static ReentrantLock lock=new ReentrantLock();
public static int i=0;
@Override
public void run() {
for (int j = 0; j <100; j++) {
lock.lock();
try{
i++;
System.out.println(Thread.currentThread().getName()+" "+i);
}finally {
lock.unlock();
}
}
}
public static void main(String[] args)throws InterruptedException{
ReenterLock r1=new ReenterLock();
Thread t1=new Thread(r1);
Thread t2=new Thread(r1);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
}
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-0 6
Thread-0 7
Thread-0 8
Thread-0 9
Thread-0 10
Thread-0 11
Thread-0 12
Thread-0 13
Thread-0 14
Thread-0 15
Thread-0 16
Thread-0 17
Thread-0 18
Thread-0 19
Thread-0 20
Thread-0 21
Thread-0 22
Thread-0 23
Thread-0 24
Thread-0 25
Thread-0 26
Thread-0 27
Thread-0 28
Thread-0 29
Thread-0 30
Thread-0 31
Thread-0 32
Thread-0 33
Thread-0 34
Thread-0 35
Thread-0 36
Thread-0 37
Thread-0 38
Thread-0 39
Thread-0 40
Thread-0 41
Thread-0 42
Thread-0 43
Thread-0 44
Thread-0 45
Thread-0 46
Thread-0 47
Thread-0 48
Thread-0 49
Thread-0 50
Thread-0 51
Thread-0 52
Thread-0 53
Thread-0 54
Thread-0 55
Thread-0 56
Thread-0 57
Thread-0 58
Thread-0 59
Thread-0 60
Thread-0 61
Thread-0 62
Thread-0 63
Thread-0 64
Thread-0 65
Thread-0 66
Thread-0 67
Thread-0 68
Thread-0 69
Thread-0 70
Thread-0 71
Thread-0 72
Thread-0 73
Thread-0 74
Thread-0 75
Thread-0 76
Thread-0 77
Thread-0 78
Thread-0 79
Thread-0 80
Thread-0 81
Thread-0 82
Thread-0 83
Thread-0 84
Thread-0 85
Thread-0 86
Thread-0 87
Thread-0 88
Thread-0 89
Thread-0 90
Thread-0 91
Thread-0 92
Thread-0 93
Thread-0 94
Thread-0 95
Thread-0 96
Thread-0 97
Thread-0 98
Thread-0 99
Thread-0 100
Thread-1 101
Thread-1 102
Thread-1 103
Thread-1 104
Thread-1 105
Thread-1 106
Thread-1 107
Thread-1 108
Thread-1 109
Thread-1 110
Thread-1 111
Thread-1 112
Thread-1 113
Thread-1 114
Thread-1 115
Thread-1 116
Thread-1 117
Thread-1 118
Thread-1 119
Thread-1 120
Thread-1 121
Thread-1 122
Thread-1 123
Thread-1 124
Thread-1 125
Thread-1 126
Thread-1 127
Thread-1 128
Thread-1 129
Thread-1 130
Thread-1 131
Thread-1 132
Thread-1 133
Thread-1 134
Thread-1 135
Thread-1 136
Thread-1 137
Thread-1 138
Thread-1 139
Thread-1 140
Thread-1 141
Thread-1 142
Thread-1 143
Thread-1 144
Thread-1 145
Thread-1 146
Thread-1 147
Thread-1 148
Thread-1 149
Thread-1 150
Thread-1 151
Thread-1 152
Thread-1 153
Thread-1 154
Thread-1 155
Thread-1 156
Thread-1 157
Thread-1 158
Thread-1 159
Thread-1 160
Thread-1 161
Thread-1 162
Thread-1 163
Thread-1 164
Thread-1 165
Thread-1 166
Thread-1 167
Thread-1 168
Thread-1 169
Thread-1 170
Thread-1 171
Thread-1 172
Thread-1 173
Thread-1 174
Thread-1 175
Thread-1 176
Thread-1 177
Thread-1 178
Thread-1 179
Thread-1 180
Thread-1 181
Thread-1 182
Thread-1 183
Thread-1 184
Thread-1 185
Thread-1 186
Thread-1 187
Thread-1 188
Thread-1 189
Thread-1 190
Thread-1 191
Thread-1 192
Thread-1 193
Thread-1 194
Thread-1 195
Thread-1 196
Thread-1 197
Thread-1 198
Thread-1 199
Thread-1 200
200
// lock.unlock();
屏蔽 lock.unlock()这行代码的打印结果,加锁后必须释放锁,否则其他线程无法获取资源
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-0 6
Thread-0 7
Thread-0 8
Thread-0 9
Thread-0 10
Thread-0 11
Thread-0 12
Thread-0 13
Thread-0 14
Thread-0 15
Thread-0 16
Thread-0 17
Thread-0 18
Thread-0 19
Thread-0 20
Thread-0 21
Thread-0 22
Thread-0 23
Thread-0 24
Thread-0 25
Thread-0 26
Thread-0 27
Thread-0 28
Thread-0 29
Thread-0 30
Thread-0 31
Thread-0 32
Thread-0 33
Thread-0 34
Thread-0 35
Thread-0 36
Thread-0 37
Thread-0 38
Thread-0 39
Thread-0 40
Thread-0 41
Thread-0 42
Thread-0 43
Thread-0 44
Thread-0 45
Thread-0 46
Thread-0 47
Thread-0 48
Thread-0 49
Thread-0 50
Thread-0 51
Thread-0 52
Thread-0 53
Thread-0 54
Thread-0 55
Thread-0 56
Thread-0 57
Thread-0 58
Thread-0 59
Thread-0 60
Thread-0 61
Thread-0 62
Thread-0 63
Thread-0 64
Thread-0 65
Thread-0 66
Thread-0 67
Thread-0 68
Thread-0 69
Thread-0 70
Thread-0 71
Thread-0 72
Thread-0 73
Thread-0 74
Thread-0 75
Thread-0 76
Thread-0 77
Thread-0 78
Thread-0 79
Thread-0 80
Thread-0 81
Thread-0 82
Thread-0 83
Thread-0 84
Thread-0 85
Thread-0 86
Thread-0 87
Thread-0 88
Thread-0 89
Thread-0 90
Thread-0 91
Thread-0 92
Thread-0 93
Thread-0 94
Thread-0 95
Thread-0 96
Thread-0 97
Thread-0 98
Thread-0 99
Thread-0 100
有显示的操作过程,必须显示指定何时加锁,何时释放锁。加锁后必须释放锁。
2重入含义
ReentrantLock是可以反复进入的,反复仅仅限于一个线程。一个线程连续两次获得同一把锁是允许的,如果不允许这种操作,线程在第二次申请锁的时候会和自己发生死锁。一个线程加多少次锁,必须释放多少次锁,如果释放的次数少,相当于线程还持有这个锁,其他线程无法
获取资源。
lock.lock();
lock.lock();
try{
i++;
System.out.println(Thread.currentThread().getName()+" "+i);
}finally {
lock.unlock();
lock.unlock();
3可中断的锁
对于synchronized来说,一个线程在等待锁,结果要么是获得锁,要么就是保持等待的状态。使用重入锁,线程在等待的过程中,程序可以根据需要取消对锁的请求。这对于处理死锁有一定帮助。
public class IntLock implements Runnable{
@Override
public void run() {
try{
if(lock==1) {
//获取锁操作
lock1.lockInterruptibly();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
lock2.lockInterruptibly();
}else{
lock2.lockInterruptibly();
try{
Thread.sleep(500);
}catch(InterruptedException e){}
lock1.lockInterruptibly();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally{
if(lock1.isHeldByCurrentThread())
lock1.unlock();
if(lock2.isHeldByCurrentThread())
lock2.unlock();
System.out.println(Thread.currentThread().getId()+":线程退出");
}
}
public static ReentrantLock lock1=new ReentrantLock();
public static ReentrantLock lock2=new ReentrantLock();
int lock;
public IntLock(int lock){
this.lock=lock;
}
public static void main(String[] args)throws InterruptedException{
IntLock r1=new IntLock(1);
IntLock r2=new IntLock(2);
Thread t1=new Thread(r1);
Thread t2=new Thread(r2);
t1.start();
t2.start();
Thread.sleep(1000);
t2.interrupt();
}
}
执行结果:
10:线程退出
9:线程退出
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
at IntLock.run(IntLock.java:22)
at java.lang.Thread.run(Thread.java:745)
Process finished with exit code 0
线程t1和t2启动后,t1先占用lock1,再占用lock2,t2先占用lock2,再占用lock1,lock.lockInterruptibly()是一个可以对中断进行响应的锁操作,即在锁的等待过程中可以响应中断。两个线程都在等待对方释放锁,两个线程处于死锁状态,执行 t2.interrupt()操作后,t2线程被中断,t2会放弃对lock1的申请,同时释放lock2,线程t1获得lock2锁,继续执行,最后两个线程都退出,t1真正完成工作,t2线程放弃任务直接退出释放资源。
4tryLock()/tryLock(long time,TimeUnit unpublic class TimeLock implements Runnable {
public static ReentrantLock lock=new ReentrantLock();
@Override
public void run() {
try{
if(lock.tryLock(5, TimeUnit.SECONDS)){
Thread.sleep(6000);
}else{
System.out.println("get lock failed");
}
}catch (InterruptedException e){
e.printStackTrace();
}finally{
if(lock.isHeldByCurrentThread())lock.unlock();
}
}
public static void main(String[] args){
TimeLock t1=new TimeLock();
Thread th1=new Thread(t1);
Thread th2=new Thread(t1);
th1.start();
th2.start();
}
}
如果超过5秒没有得到锁就会返回false,占用锁的线程持用锁的时间长达6秒,因此另外一个线程无法在5秒的等待时间内获得锁。
锁在大多数情况下,锁的申请都是非公平的,系统会随机地从锁的等待队列中挑选一个。公平的锁会按时间先后顺序,保证先到者先得后到者后得。公平锁的一大特点是:不会产生饥饿。在使用synchronized关键字进行锁控制时,产生的锁是非公平的。
公平锁的创建:
public ReentrantLock(boolean fair)
ReentrantLock lock=new ReentrantLock(true);
实现公平锁必然要维护一个有序队列,因此公平锁的实现成本比较高,性能相对也非常低,默认情况下,锁是非公平的。
public class FairLock implements Runnable {
public static ReentrantLock fairLock = new ReentrantLock(true);
@Override
public void run() {
while (true) {
try {
fairLock.lock();
System.out.println(Thread.currentThread().getName() + "获得锁");
} finally {
fairLock.unlock();
}
}
}
public static void main(String[] args) {
FairLock r1 = new FairLock();
Thread t1 = new Thread(r1, "Thread_t1");
Thread t2 = new Thread(r1, "Thread_t2");
t1.start();
t2.start();
}
}
结果:t1 t2交替获得锁
Thread_t2获得锁
Thread_t1获得锁
Thread_t2获得锁
Thread_t1获得锁
Thread_t2获得锁
Thread_t1获得锁
Thread_t2获得锁
Thread_t1获得锁
Thread_t2获得锁
Reentrantlock重要方法整理
lock():获得锁,如果锁被占用,则等待
lockInterruptibly():获得锁,但优先响应中断
tryLock():尝试获得锁,如果成功返回true,失败则返回false。该方法不等待,立即返回。
tryLock(long time,TimeUnit unit):在给定时间内尝试获得锁
unlock():释放锁
重入锁的实现要素:
1原子状态:原子状态使用CAS操作来存储当前锁的状态,判断锁是否已经被别的线程持有。
2等待队列:所有没请求到锁的线程,会进入等待队列等待。待有线程释放锁,系统就能从等待队列中唤醒一个线程,继续工作。
3阻塞原语park()和unpark(),用来挂起和恢复线程。没有得到锁的线程将会被挂起。