import java.util.concurrent.locks.ReentrantLock;
/**
* 重入锁 ReenterLock 一个线程允许连续获得同一把锁,注意:必须释放相同次数,释放次数多,会异常,少了相当于线程还持有这个锁,其他线程无法进入临界区
* 需要手动指定何时加锁何时释放锁
*
ReenterLock几个重要方法:
- lock():获得锁,如果锁已经被占用,则等待
- lockInterruptibly():获得锁,但优先响应中断
- tryLock():尝试获得锁,成功返回true,失败返回false,该方法不等待,立即返回
- tryLock(long time,TimeUnit unit):在给定时间内尝试获得锁
- unlock():释放锁
*/
public class ReentrantLockDemo implements Runnable{
public static Integer i = 0;
public static ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
for (int j = 0; j < 10000000; j++) {
lock.lock();
try {
i++;
}finally {
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException{
ReentrantLockDemo r = new ReentrantLockDemo();
Thread thread1 = new Thread(r);
Thread thread2 = new Thread(r);
thread1.start();thread2.start();
thread1.join();thread2.join();
System.out.println(i);//20000000
}
}
中断处理
import java.util.concurrent.locks.ReentrantLock;
/**
* 避免死锁
* 重入锁的中断处理能力
*/
public class IntLock implements Runnable{
public static ReentrantLock lock1 = new ReentrantLock();
public static ReentrantLock lock2 = new ReentrantLock();
int lock;
public IntLock(int lock) {
this.lock = lock;
}
@Override
public void run() {
try {
if (lock==1){
lock1.lockInterruptibly();
Thread.sleep(500);
lock2.lockInterruptibly();//可以对中断进行响应的锁
}else {
lock2.lockInterruptibly();
Thread.sleep(500);
lock1.lockInterruptibly(); //22行
}
}catch (InterruptedException e){
e.printStackTrace();
}finally {
//检查当前线程是否拥有该锁
if (lock1.isHeldByCurrentThread()) lock1.unlock();
if (lock2.isHeldByCurrentThread()) lock2.unlock();
System.out.println(Thread.currentThread().getId()+":线程退出");
}
}
public static void main(String[] args) throws InterruptedException{
IntLock i1 = new IntLock(1);
IntLock i2 = new IntLock(2);
Thread t1 = new Thread(i1);
Thread t2 = new Thread(i2);
t1.start();
t2.start();
Thread.sleep(1000);
t2.interrupt(); //中断t2 ,t2放弃对lock1的申请,同时释放已获得的lock2
//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 com.combat.IntLock.run(IntLock.java:22)
// at java.lang.Thread.run(Thread.java:748)
//10:线程退出
//9:线程退出
}
}
限时等待
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
* 限时等待锁
*/
public class TimeLockDemo 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){
TimeLockDemo demo = new TimeLockDemo();
Thread t1 = new Thread(demo);
Thread t2 = new Thread(demo);
t1.start();
t2.start();
}
//get lock failed
//由于占用锁的线程为6秒,另一个线程无法在5秒的等待时间内获得锁,因此请求锁失败
}
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
* tryLock
* 限时等待锁 无参数 如果锁被其他线程占用,则当前线程不会进行等待,而是立即返回false,不会引起线程等待
*/
public class TimeLockDemo2 implements Runnable{
public static ReentrantLock lock1 = new ReentrantLock();
public static ReentrantLock lock2 = new ReentrantLock();
int lock;
public TimeLockDemo2(int lock) {
this.lock = lock;
}
@Override
public void run() {
if (lock == 1){
while (true){
if (lock1.tryLock()){
try {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (lock2.tryLock()){
try {
System.out.println(Thread.currentThread().getId()+":my job done");
return;
} finally {
lock2.unlock();
}
}
} finally {
lock1.unlock();
}
}
}
}else {
while (true){
if (lock2.tryLock()){
try {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (lock1.tryLock()){
try {
System.out.println(Thread.currentThread().getId()+":my job done");
return;
} finally {
lock1.unlock();
}
}
} finally {
lock2.unlock();
}
}
}
}
}
public static void main(String[] args){
TimeLockDemo2 r1 = new TimeLockDemo2(1);
TimeLockDemo2 r2 = new TimeLockDemo2(1);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
//9:my job done
//10:my job done
}
公平锁
import java.util.concurrent.locks.ReentrantLock;
/**
* 公平锁
* synchronized产生的锁是非公平锁
* 重入锁可以设置公平性
*/
public class FairLock implements Runnable{
public static ReentrantLock lock = new ReentrantLock(true);
@Override
public void run() {
while (true){
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+"获得锁");
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException{
FairLock lock = new FairLock();
Thread t1 = new Thread(lock, "thread_t1");
Thread t2 = new Thread(lock, "thread_t2");
t1.start();
t2.start();
}
//...
//thread_t2获得锁
//thread_t1获得锁
//thread_t2获得锁
//thread_t1获得锁
//thread_t2获得锁
//...
//两个线程基本交替获得锁
//而非公平锁,一个线程会倾向于再次获得已持有的锁,这种分配方式是高效的,但无公平性可言
}