Lock是一个接口,提供了无条件的、可轮询的、定时的、可中断的锁获取操作,所有加锁和解锁的方法都是显式的。
包路径是:java.util.concurrent.locks.Lock
核心方法是lock()、unlock()、tryLock()
实现类有ReentrantLock、ReentrantReadWriteLock.ReadLock、ReentrantReadWriteLock.WriteLock
下图展示了Lock接口中定义的方法:
Java中synchronized 和 ReentrantLock 有什么不同?
Java在过去很长一段时间只能通过synchronized关键字来实现互斥,它有一些缺点。比如你不能扩展锁之外的方法或者块边界,尝试获取锁时不能中途取消等。Java 5 通过Lock接口提供了更复杂的控制来解决这些问题。ReentrantLock是Lock的实现类,它拥有与synchronized相同的并发性和内存语义且它还具有可扩展性。
此处我们看一下下面这两段代码,请注意这两种方式的区别:
(1)此处两个方法之间的锁是独立的
package com.test; import java.util.concurrent.locks.ReentrantLock; public class ReentrantLockDemo { public static void main(String[] args) { final Countx ct = new Countx(); for (int i = 0; i < 2; i++) { new Thread() { @Override public void run() { ct.get(); } }.start(); } for (int i = 0; i < 2; i++) { new Thread() { @Override public void run() { ct.put(); } }.start(); } } } class Countx { public void get() { final ReentrantLock lock = new ReentrantLock(); try { lock.lock();// 加锁 System.out.println(Thread.currentThread().getName() + "get begin"); Thread.sleep(1000L);// 模仿干活 System.out.println(Thread.currentThread().getName() + "get end"); lock.unlock(); // 解锁 } catch (InterruptedException e) { e.printStackTrace(); } } public void put() { final ReentrantLock lock = new ReentrantLock(); try { lock.lock();// 加锁 System.out.println(Thread.currentThread().getName() + "put begin"); Thread.sleep(1000L);// 模仿干活 System.out.println(Thread.currentThread().getName() + "put end"); lock.unlock(); // 解锁 } catch (InterruptedException e) { e.printStackTrace(); } } }
运行结果如下(每次运行结果都是不一样的,仔细体会一下):
Thread-1get begin Thread-0get begin Thread-2put begin Thread-3put begin Thread-0get end Thread-3put end Thread-1get end Thread-2put end
(2)此处两个方法之间使用相同的锁
package com.test; import java.util.concurrent.locks.ReentrantLock; public class ReentrantLockDemo { public static void main(String[] args) { final Countx ct = new Countx(); for (int i = 0; i < 2; i++) { new Thread() { @Override public void run() { ct.get(); } }.start(); } for (int i = 0; i < 2; i++) { new Thread() { @Override public void run() { ct.put(); } }.start(); } } } class Countx { final ReentrantLock lock = new ReentrantLock(); public void get() { // final ReentrantLock lock = new ReentrantLock(); try { lock.lock();// 加锁 System.out.println(Thread.currentThread().getName() + "get begin"); Thread.sleep(1000L);// 模仿干活 System.out.println(Thread.currentThread().getName() + "get end"); lock.unlock(); // 解锁 } catch (InterruptedException e) { e.printStackTrace(); } } public void put() { // final ReentrantLock lock = new ReentrantLock(); try { lock.lock();// 加锁 System.out.println(Thread.currentThread().getName() + "put begin"); Thread.sleep(1000L);// 模仿干活 System.out.println(Thread.currentThread().getName() + "put end"); lock.unlock(); // 解锁 } catch (InterruptedException e) { e.printStackTrace(); } } }
运行结果如下(每次运行结果都是一样的):
Thread-0get begin Thread-0get end Thread-1get begin Thread-1get end Thread-2put begin Thread-2put end Thread-3put begin Thread-3put end
时间: 2024-10-08 14:36:15