Java高并发程序-Chapter3 JDK并发包(第九讲)同步控制之 ReentrantLock 重用锁
2018-03-27 13:23
567 查看
ReentrantLock 重用锁
1. 可重用
import java.util.concurrent.locks.ReentrantLock;
public class ReenterLock implements Runnable {
public static ReentrantLock reentrantLock = new ReentrantLock();
public static int i = 0;
public void run() {
for (int j = 0; j < 1000000; j++) {
try {
reentrantLock.lock();
reentrantLock.lock(); //可重用
i++;
} finally {
reentrantLock.unlock();
reentrantLock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
ReenterLock reenterLock = new ReenterLock();
Thread t1 = new Thread(reenterLock);
Thread t2 = new Thread(reenterLock);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
}在这种情况下,一个线程连续两次获得同一把锁。这是允许的!
如果不允许这么操作,那么同一个线程在第2次获得锁时,将会和自己产生死锁。
程序就会“卡死”在第2次申请锁的过程中。
但需要注意的是,如果同一个线程多次获得锁,那么在释放锁的时候,也必须释放相同次数
如果释放锁的次数多,那么会得到一个 java. lang. legalmonitorstateexception异常,反之,如果释放锁的次数少了,那么相当于线程还持有这个锁。
2. 可中断package com.john.learn.high.concurent.ch03;
import java.util.concurrent.locks.ReentrantLock;
public class InterruptLock implements Runnable {
public static ReentrantLock lock1 = new ReentrantLock();
public static ReentrantLock lock2 = new ReentrantLock();
private int lock;
public InterruptLock(int lock) {
this.lock = lock;
}
public void run() {
try {
if (lock == 1) {
try {
lock1.lockInterruptibly();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
lock2.lockInterruptibly();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return;
}
try {
lock2.lockInterruptibly();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
lock1.lockInterruptibly();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return;
} finally {
if (lock1.isHeldByCurrentThread()) {
lock1.unlock();
}
if (lock2.isHeldByCurrentThread()) {
lock2.unlock();
}
System.out.println(Thread.currentThread().getName() + ":退出.");
}
}
public static void main(String[] args) throws InterruptedException {
InterruptLock lock1 = new InterruptLock(1);
InterruptLock lock2 = new InterruptLock(2);
Thread thread1 = new Thread(lock1);
Thread thread2 = new Thread(lock2);
thread1.start();
thread2.start();
Thread.sleep(5000);
//中断一个线程
thread2.interrupt();
}
}
线程t1和t2启动后,t1先占用lock1,再占用lock2; t2先占用lock2,再请求lock1。
因此很容易形成t1和t2之间的相互等待。
在这里,对锁的请求,统一使用lockInterruptibly()方法
这是一个可以对中断进行响应的锁申请动作,即在等待锁的过程中,可以响应中断在代码第47行,主线程main处于休眠
,此时,这两个线程处于死锁的状态,在代码第49行,由于t2线程被中断,故t2会放弃对locki的申请,同时释放已获得lock2。
这个操作导致t1线程可以顺利得到lock2而继续执行下去。
执行上述代码,将输出:
3.可限时package com.john.learn.high.concurent.ch03;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class TimeLock implements Runnable {
public ReentrantLock lock = new ReentrantLock();
public void run() {
try {
if (lock.tryLock(5, TimeUnit.SECONDS)) {
System.out.println("Get lock successful and in processing. "+ Thread.currentThread().getName());
Thread.sleep(6000);
return;
}
System.out.println("Get lock failed. " + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
TimeLock timeLock = new TimeLock();
Thread thread1 = new Thread(timeLock);
Thread thread2 = new Thread(timeLock);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
}
在这里, tryLock()方法接收两个参数,一个表示等待时长,另外一个表示计时单位。
这里的单位设置为秒,时长为5,表示线程在这个锁请求中,最多等待5秒。
如果超过5秒还没有得到锁,就会返回 false。
如果成功获得锁,则返回true在本例中,由于占用锁的线程会持有锁长达6秒,故另一个线程无法在5秒的等待时间内获得锁,因此,请求锁会失败。
Reentrantlock.tryLock()方法也可以不带参数直接运行。
在这种情况下,当前线程会尝试获得锁,如果锁并未被其他线程占用,则申请锁会成功,并立即返回true。
如果锁被其他线程占用,则当前线程不会进行等待,而是立即返回 false。
这种模式不会引起线程等待,因此也不会产生死锁。
输出:
4. 公平锁
public ReentrantLock(boolean fair)
public static ReentrantLock fairLock = new ReentrantLock(true);
相关文章推荐
- Java高并发程序-Chapter3 JDK并发包(第十七讲)同步控制之ReentrantLock 的实现
- Java高并发程序-Chapter3 JDK并发包(第十六讲)同步控制之LockSupport
- Java高并发程序-Chapter3 JDK并发包(第十二讲)同步控制之 ReadWriteLock
- Java高并发程序-Chapter3 JDK并发包(第十八讲)同步控制之自定义SafeQueue
- Java高并发程序-Chapter3 JDK并发包(第十讲)同步控制之 Condition
- Java高并发程序-Chapter3 JDK并发包(第十一讲)同步控制之 Semaphore
- Java高并发程序-Chapter3 JDK并发包(第十三讲)同步控制之 CoutDownLatch
- Java高并发程序-Chapter3 JDK并发包(第十四讲)同步控制之自己动手实现 CoutDownLatch
- Java高并发程序-Chapter3 JDK并发包(第十五讲)同步控制之CyclicBarrier 循环栅栏
- java高并发程序设计总结三:JDK并发包之ReentrantLock重入锁
- java并发控制:ReentrantLock Condition使用详解
- Java 并发及同步相关 Synchronized ReentrantLock
- Java并发--互斥同步--synchronized和ReentrantLock比较
- Java高并发程序-Chapter3 JDK并发包(第二十一讲)JDK 并发容器
- java并发控制:ReentrantLock Condition使用详解
- Java高并发程序设计笔记5之JDK同步控制
- Java高并发程序-Chapter3 JDK并发包(第十九讲)线程复用:线程池
- Java乐观锁悲观锁、synchronized,重入锁 (ReentrantLock)处理并发(互斥同步、非互斥同步)
- Java高并发程序-Chapter3 JDK并发包(第二十讲)Fork/Join
- Java并发--互斥同步--Java两种锁机制synchronized和ReentrantLock详解