相对于 synchronized 它具备如下特点:
基本语法:
// 获取锁 reentrantLock.lock(); try { // 临界区 } finally { // 释放锁 reentrantLock.unlock(); }
示例代码:
package tian; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.locks.ReentrantLock; @Slf4j(topic = "c.Test22") public class Test22 { private static final ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) { lock.lock(); try { log.debug("Enter Main"); m1(); } catch (Exception e) { lock.unlock(); } } public static void m1() { lock.lock(); try { log.debug("Enter m1"); m2(); } catch (Exception e) { lock.unlock(); } } public static void m2() { lock.lock(); try { log.debug("Enter m2"); } catch (Exception e) { lock.unlock(); } } }
运行结果:
示例代码:
@Slf4j(topic = "c.Test22") public class Test22 { private static final ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) { Thread t1 = new Thread(() -> { log.debug("启动..."); try { // ReentrantLock对象的lockInterruptibly()方法可以被打断 lock.lockInterruptibly(); } catch (InterruptedException e) { e.printStackTrace(); log.debug("等锁的过程中被打断"); return; } try { log.debug("获得了锁"); } finally { lock.unlock(); } }, "t1"); lock.lock(); log.debug("获得了锁"); t1.start(); try { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } t1.interrupt(); log.debug("执行打断"); } finally { lock.unlock(); } }
运行结果:
lock.tryLock(2, TimeUnit.SECONDS)方法可以设置尝试获取锁的最大等待时间,如果超过了最大等待时间,则获取不到锁。这个方法返回一个布尔值,如果或得到了锁,则返回true否则返回false。如果这个方法不加参数,那么会一直尝试去获取锁。
代码:
package tian; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; @Slf4j(topic = "c.Test22") public class Test22 { private static ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { log.debug("尝试获得锁"); try { if (!lock.tryLock(2, TimeUnit.SECONDS)) { log.debug("获取不到锁"); return; } } catch (InterruptedException e) { e.printStackTrace(); log.debug("获取不到锁"); return; } try { log.debug("获得到锁"); } finally { lock.unlock(); } }, "t1"); lock.lock(); log.debug("获得到锁"); t1.start(); Thread.sleep(3000); log.debug("释放了锁"); lock.unlock(); } }
运行结果:
代码:
运行结果:
代码:
package tian; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.locks.ReentrantLock; @Slf4j(topic = "c.Test23") public class Test23 { public static void main(String[] args) { Chopstick c1 = new Chopstick("1"); Chopstick c2 = new Chopstick("2"); Chopstick c3 = new Chopstick("3"); Chopstick c4 = new Chopstick("4"); Chopstick c5 = new Chopstick("5"); new Philosopher("苏格拉底", c1, c2).start(); new Philosopher("柏拉图", c2, c3).start(); new Philosopher("亚里士多德", c3, c4).start(); new Philosopher("赫拉克利特", c4, c5).start(); new Philosopher("阿基米德", c5, c1).start(); } } @Slf4j(topic = "c.Philosopher") class Philosopher extends Thread { Chopstick left; Chopstick right; public Philosopher(String name, Chopstick left, Chopstick right) { super(name); this.left = left; this.right = right; } @Override public void run() { while (true) { // 尝试获得左手筷子 if (left.tryLock()) { try { // 尝试获得右手筷子 if (right.tryLock()) { try { eat(); } finally { right.unlock(); } } } finally { // 如果没有获得右手的筷子 则释放自己手里的筷子 这里是解决哲学家就餐问题的关键 left.unlock(); } } } } private void eat() { log.debug("eating..."); try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } } } class Chopstick extends ReentrantLock { String name; public Chopstick(String name) { this.name = name; } @Override public String toString() { return "筷子{" + name + '}'; } }
运行结果: