1、ReentrantLock是一种可重入锁,可以替代synchronized
子类和父类如果都是synchronized(this)就是同一把锁。sync实现:
public class Thread_007_ReentrantLock {
public static void main(String[] args) {
Thread_007_ReentrantLock thread007ReentrantLock = new Thread_007_ReentrantLock();
new Thread(thread007ReentrantLock::m1).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized void m1() {
for (int i = 0; i < 10; i++) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("m1----start" + i);
if (2 == i) {
m2();
}
}
}
synchronized void m2() {
System.out.println("m2----start");
}
}
运行结果:
m1----start0
m1----start1
m1----start2
m2----start
m1----start3
m1----start4
m1----start5
m1----start6
m1----start7
m1----start8
m1----start9
ReentrantLock替代sync实现可重入但是sync是自动解锁,但是ReentrantLock必须手动解锁,try…finally{lock.unlock()}:
public class Thread_008_ReentrantLock {
public static void main(String[] args) {
Thread_008_ReentrantLock thread008ReentrantLock = new Thread_008_ReentrantLock();
new Thread(thread008ReentrantLock::m1).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(thread008ReentrantLock::m2).start();
}
Lock lock = new ReentrantLock();
void m1() {
// 相当于synchronized(this)
try {
lock.lock();
for (int i = 0; i < 10; i++) {
TimeUnit.SECONDS.sleep(1);
System.out.println("m1-----start" + i);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 必须手动释放锁
lock.unlock();
}
}
void m2() {
try {
lock.lock();
System.out.println("m2----start");
} finally {
lock.unlock();
}
}
}
运行结果:
m1----start0
m1----start1
m1----start2
m2----start
m1----start3
m1----start4
m1----start5
m1----start6
m1----start7
m1----start8
m1----start9
m2----start
2、ReentrantLock特别的功能可以使用trylock进行尝试锁定,不管锁定与否,方法都将继续进行,synchronized如果搞不定就肯定阻塞了,ReentrantLock可以自己决定到底要不要wait
public class Thread_009_ReentrantLcok {
private Lock lock = new ReentrantLock();
public static void main(String[] args) {
Thread_009_ReentrantLcok thread009ReentrantLcok = new Thread_009_ReentrantLcok();
new Thread(thread009ReentrantLcok::m1).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(thread009ReentrantLcok::m2).start();
}
void m1() {
try {
lock.lock();
for (int i = 0; i < 6; i++) {
TimeUnit.SECONDS.sleep(1);
System.out.println("m1-----start-Thread-" + i);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
/**
* @Description TODO
* 使用trylock进行尝试锁定,不管锁定与否,方法都将继续进行
* 可以根据trylock的返回值来判断是否锁定
* 也可指定trylock的时间
* @ClassName Thread_009_ReentrantLcok
* @Author Elvin
* @Date 2020/12/5 16:22
* @Version 1.0
*/
void m2() {
boolean locked = false;
// 方式一:可以根据trylock的返回值来判断是否锁定
try {
locked = lock.tryLock();
System.out.println("m2----start----" + locked);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (locked) {
lock.unlock();
}
}
// 方式二
/*try {
locked = lock.tryLock(5, TimeUnit.SECONDS);
System.out.println("m2----start----" + locked);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (locked) {
lock.unlock();
}
}*/
}
}
运行结果:
m1-----start-Thread-0
m2----start----false
m1-----start-Thread-1
m1-----start-Thread-2
m1-----start-Thread-3
m1-----start-Thread-4
m1-----start-Thread-5
3、ReentrantLock还可以用lock.lockinterruptibly(),对interrupt(0方法做出回应,可以被打断的加锁
public class Thread_010_ReentrantLock {
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Thread thread1 = new Thread(()->{
try {
lock.lock();
System.out.println("thread1 start");
TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
System.out.println("thread1 end");
} catch (InterruptedException e) {
System.out.println("thread1 interrupted");
} finally {
lock.unlock();
}
});
thread1.start();
Thread thread2 = new Thread(()->{
try {
// lock.lock();
lock.lockInterruptibly();
System.out.println("thread2 start");
TimeUnit.SECONDS.sleep(5);
System.out.println("thread2 end");
} catch (InterruptedException e) {
System.out.println("thread2 interrupted");
} finally {
lock.unlock();
}
});
thread2.start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread2.interrupt();
}
}
运行结果:
thread1 start
thread2 interrupted
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
at com.xjc.study.thread.Thread_010_ReentrantLock.lambda$main$1(Thread_010_ReentrantLock.java:45)
at java.lang.Thread.run(Thread.java:748)
4、ReentrantLock还可以指定为公平锁,所谓公平锁就是后来的线程在队列中等待,让已有线程先执行完了在执行后来的。ReentrantLock默认是非公平锁。ReentrantLock(true)的时候才是公平锁。
public class Thread_011_ReentrantLcok extends Thread {
public static void main(String[] args) {
Thread_011_ReentrantLcok thread011ReentrantLcok = new Thread_011_ReentrantLcok();
Thread thread1 = new Thread(thread011ReentrantLcok);
Thread thread2 = new Thread(thread011ReentrantLcok);
thread1.start();
thread2.start();
}
private static ReentrantLock lock = new ReentrantLock(true);
public void run() {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "-" +i + "获得锁");
} finally {
lock.unlock();
}
}
}
}
运行结果:
Thread-1-0获得锁
Thread-1-1获得锁
Thread-1-2获得锁
Thread-1-3获得锁
Thread-1-4获得锁
Thread-1-5获得锁
Thread-1-6获得锁
Thread-1-7获得锁
Thread-1-8获得锁
Thread-1-9获得锁
Thread-2-0获得锁
Thread-2-1获得锁
Thread-2-2获得锁
Thread-2-3获得锁
Thread-2-4获得锁
Thread-2-5获得锁
Thread-2-6获得锁
Thread-2-7获得锁
Thread-2-8获得锁
Thread-2-9获得锁