+ ReentrantLock类的使用
+ ReentrantReadWriteLock类的使用
ReentrantLock类能够实现线程之间同步互斥,并且在扩展功能上更加强大,例如嗅探技术
、多路分支通知
等功能,在使用上比synchronized
更加灵活。
ReentrantLock类具有完全互斥排他的效果,即同一时间只有一个线程在执行ReentrantLock.lock()
方法后面的任务。
ReentrantLock
实现了Lock
接口,该接口包含以下方法:
public interface Lock { void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock(long time, TimeUnit unit) throws InterruptedException; void unlock(); Condition newCondition(); }
关键字synchronized
与wait()
和notify()
/notifyAll()
方法结合可以实现等待/通知模型,ReentrantLock
类也可以实现同样的功能,需要借助Condition
对象。Condition
对象是JDK1.5中出现的技术,它有更好的灵活性,比如可实现多路通知功能,也就是在一个Lock
对象里面可以创建多个Condition
(即对象监视器)实例,线程对象可以注册在指定的Condition
中,从而可以有选择性地进行线程通知,在调度线程上更加灵活。
使用notify()
/notifyAll()
方法进行通知时,被通知的线程由JVM随机选择。通过ReentrantLock
结合Condition
可以实现选择性通知。synchronized
相当于整个Lock
对象中只有一个单一的Condition
对象,所有的线程都注册在它一个对象的身上。线程notifyAll()
时,需要通知所有的WAITING
线程,没有选择权。
Object类中的wait()
方法相当于Condition类中的await()
方法。
Object类中的wait(long timeout)
方法相当于Condition类中的await(long time,TimeUnit unit)
方法。
Object类中的notify()
方法相当于Condition类中的signal()
方法。
Object类中的notifyAll()
方法相当于Condition类中的signalAll()
方法。
Lock分为公平锁和非公平锁,公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配的,即先来先得的FIFO先进先出顺序。非公平锁是一种获取锁的抢占机制,是随机获得锁的。
int getHoldCount()
的作用是查询当前线程保持此锁定的个数,也就是调用lock()方法的次数。int getQueueLength()
的作用是返回正在等待获取此锁定的线程估计数int getWaitQueueLength(Condition condition)
的作用是返回等待与此锁定相关的给定条件Condition的线程估计数。比如有5个线程,每个线程都执行了同一个condition对象的await()方法,则调用getWaitQueueLength(condition)方法返回的指为5.boolean hasQueuedThread(Thread thread)
的作用是查询指定的线程是否正在等待获取此锁定。boolean hasQueuedThreads()
的作用是差选是否有线程正在等待获取此锁定。boolean hasWaiters(Condition condition)
的作用是查询是否有线程正在等待与此锁定有关的condition条件。boolean isFair()
的作用是判断是不是公平锁。boolean isHeldByCurrentThread()
的作用是查询当前线程是否保持此锁定。boolean isLocked()
的作用是查询此锁定是否由任意线程保持。void lockInterruptibly()
的作用是:如果当前线程未被中断,则获取锁定;如果已经被中断则抛出异常(java.lang.InterruptedException).boolean tryLock()
的作用是:仅在调用时锁未被另外线程保持的情况下,才获取此锁定。boolean tryLock(long timeout,TimeUnit unit)
的作用是:如果锁定在给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获取该锁定。使用Condition对象可以对线程执行的业务进行排序规划
读写锁有两个锁:一个是读操作相关的锁,也称为共享锁;一个是写操作相关的锁,也称为排他锁。
多个读锁之间不互斥;读锁与写锁互斥;写锁与写锁互斥。
package com.zxd.concurrent.learning; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author CoderZZ * @Title: ${FILE_NAME} * @Project: ConcurrentLearning * @Package com.zxd.concurrent.learning * @description: 读锁不互斥;读写、写写互斥 * @Version 1.0 * @create 2018-04-08 21:29 **/ public class ReentrantReadWriteLockTest { private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(); public void read(){ try { reentrantReadWriteLock.readLock().lock(); System.out.println("获得读锁"+Thread.currentThread().getName()+" timestamp:"+System.currentTimeMillis()); Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); }finally { reentrantReadWriteLock.readLock().unlock(); } } public void write(){ try{ reentrantReadWriteLock.writeLock().lock(); System.out.println("获得写锁"+Thread.currentThread().getName()+" timestamp:"+System.currentTimeMillis()); Thread.sleep(10000); }catch (Exception e){ e.printStackTrace(); }finally { reentrantReadWriteLock.writeLock().unlock(); } } public static void main(String[] args){ ReentrantReadWriteLockTest reentrantReadWriteLockTest = new ReentrantReadWriteLockTest(); Runnable readRunnable = new Runnable() { @Override public void run() { reentrantReadWriteLockTest.read(); } }; Thread threadA = new Thread(readRunnable); threadA.setName("A"); threadA.start(); Thread threadB = new Thread(readRunnable); threadB.setName("B"); threadB.start(); Runnable writeRunnable = new Runnable() { @Override public void run() { reentrantReadWriteLockTest.write(); } }; Thread writeA = new Thread(writeRunnable); writeA.setName("writeA"); writeA.start(); Thread writeB = new Thread(writeRunnable); writeB.setName("writeB"); writeB.start(); } }
运行结果如下:
原文:https://www.cnblogs.com/Java-Script/p/11090619.html