1.ReentrantLock
调用ReentrantLock对象的lock() 方法获取锁,调用unlock() 方法释放锁。
(1) 使用Condition实现等待/通知
synchronized关键字使用wait() 和 notify() / notifyAll() 方法相结合可以实现等待/通知模式,ReentrantLock类也可以实现同样的功能,但需要借助于 Condition对象。 Condition类有更好的灵活性,比如可以实现多路通知功能,线程对象可以注册在指定的Condition中,从而可以有选择性地进行线程通知,在调度线程上更加灵活。而使用 notify() /notifyAll() 方法进行通知时,被通知的线程却是由JVM随机选择的。
线程执行 notifyAll() 时,需要通知所有的WAITING线程,没有选择权,会出现相当大的效率问题。
public class Service {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
...
public void await() {
try {
lock.lock();
System.out.println("await开始时间:" + System.currentTimeMillis());
condition.await();
System.err.println("await结束时间:" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void signal() {
try {
lock.lock();
System.out.println("signal唤醒时间:" + System.currentTimeMillis());
condition.signal();
} finally {
lock.unlock();
}
}
}
public class ThreadIX extends Thread {
private Service service;
public ThreadIX(Service service) {
this.service = service;
}
@Override
public void run() {
service.await();
}
}
public class RunMain {
public static void main(String[] args) throws InterruptedException {
Service service = new Service();
ThreadIX thread = new ThreadIX(service);
thread.start();
Thread.sleep(3000);
service.signal();
}
}
运行结果:
成功实现等待/通知模式:
Object 类中的wait() 方法相当于 Condition类中的await() 方法。
Object 类中的 wait(long timeout)方法相当于 Condition类中的 await(long time, TimeUnit unit)方法。
Object 类中的 notify() 方法相当于 Condition类中的 signal() 方法。
Object 类中的 notifyAll() 方法相当于 Condition类中的 signalAll() 方法。
2. ReentrantReadWriteLock
ReentrantLock类具有完全互斥排他的效果,即同一时间只有一个线程在执行ReentrantLock.lock() 方法后面的任务。这样做虽然保证了实例变量的线程安全性,但效率却是非常低的。
ReentrantReadWriteLock类可以加快运行效率。读写锁有两个锁:一个是读操作相关的共享锁;另一个是写操作相关的排他锁。(多个读锁之间不互斥,读锁与写锁、写锁与写锁之间互斥)即多个 Thread可以同时进行读取操作,但是同一时刻只允许一个 Thread进行写入操作。
public class Service {
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void threadLock() {
try {
lock.readLock().lock();
System.out.println("读锁" + Thread.currentThread().getName()+" : " + System.currentTimeMillis());
Thread.sleep(2000);
System.err.println("结束时间:"+System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.readLock().unlock();
}
}
}
public class ThreadIX extends Thread {
private Service service;
public ThreadIX(Service service) {
this.service = service;
}
@Override
public void run() {
service.threadLock();
}
}
public class RunMain {
public static void main(String[] args) {
Service service = new Service();
ThreadIX threadA = new ThreadIX(service);
threadA.setName("A");
threadA.start();
ThreadIX threadB = new ThreadIX(service);
threadB.setName("B");
threadB.start();
}
}
运行结果: