java中Rlock类的使用_Java Lock的使用

1. ReentrantLock 类

调用ReentrantLock对象的lock()方法获取锁,调用unlock()方法释放锁

class MyService{

private Lock lock = new ReentrantLock();

public void testMethod() {

lock.lock();

for (int i = 0;i < 5;i++) {

System.out.println(Thread.currentThread().getName() + "..." + (i+1) + "...ing");

}

lock.unlock();

}

}

class MyThread extends Thread {

private MyService myService;

public MyThread(MyService myService) {

this.myService = myService;

}

@Override

public void run() {

myService.testMethod();

}

}

public static void main(String[] args) {

MyService service = new MyService();

MyThread t1 = new MyThread(service);

MyThread t2 = new MyThread(service);

MyThread t3 = new MyThread(service);

MyThread t4 = new MyThread(service);

MyThread t5 = new MyThread(service);

t1.start();

t2.start();

t3.start();

t4.start();

t5.start();

}

1.1 使用Condition实现等待/通知

关键字synchronized与wait()和notify()/notifyAll()方法相结合可以实现等待/通知模式,类ReentrantLock也可以借助Condition对象实现

class MyCondition {

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.out.println("被signal()唤醒:" + System.currentTimeMillis());

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

lock.unlock();

}

}

public void signal() {

try {

lock.lock();

condition.signal();

} finally {

lock.unlock();

}

}

}

public static void main(String[] args) {

try {

MyCondition myCondition = new MyCondition();

Thread A = new Thread() {

@Override

public void run() {

myCondition.await();

}

};

Thread B = new Thread() {

@Override

public void run() {

myCondition.signal();

}

};

A.start();

Thread.sleep(3000);

B.start();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

//await():1566072576879

//被signal()唤醒:1566072579873

condition.await() 方法调用之前需要调用lock.lock() 获得同步监视器

object.wait() 相当于 condition.await()

object.wait(long) 相当于 condition.await(long, TimeUnit)

object.notify() 相当于 condition.signal()

object.notifyAll() 相当于 condition.signalAll()

1.1.1 唤醒指定种类的线程

private Condition conditionA = lock.newCondition();

private Condition conditionB = lock.newCondition();

...

{

conditionA.await(); //A类等待

}

{

conditionB.await(); //B类等待

}

{

conditionA.signalAll(); //唤醒A类等待

}

{

conditionB.signalAll(); //唤醒B类等待

}

1.2 公平锁和非公平锁

锁Lock分为 公平锁 和 非公平锁,

公平锁表示线程获取锁的的顺序是按照线程加锁的顺序来分配的

非公平锁随机获得

Lock lock = new ReentrantLock(true/false) 公平/非公平

默认情况下,ReentrantLock类使用的是非公平锁

1.3 getHoldCount()、getQueueLength()、getWaitQueueLength()

getHoldCount() 查询当前线程保持此锁定的个数,也就是调用lock()方法的次数 class HoldCount {

private ReentrantLock lock = new ReentrantLock();

public void method1() {

try {

lock.lock();

method2();

} finally {

lock.unlock();

}

}

public void method2() {

try {

lock.lock();

System.out.println("lock.getHoldCount(): " + lock.getHoldCount());

} finally {

lock.unlock();

}

}

}

public static void main(String[] args) {

HoldCount holdCount = new HoldCount();

holdCount.method1();

}

//lock.getHoldCount(): 2

lock.getQueueLength() 作用是返回正在等待获取此锁定的线程估计数,就是有多少线程同时在等待lock的释放

lock.getWaitQueueLength(Condition condition) 作用是返回等待与此锁定相关的给定条件Condition的线程估计数。有5个线程执行了同一个condition对象的await()方法,返回5

1.4 hasQueuedThread()、hasQueuedThreads()、hasWaiters()

lock.hasQueuedThread(Thread thread) 作用是查询指定的线程是否正在等待获取此锁定

lock.hasQueuedThreads() 作用是查询是否有线程正在等待获取此锁定

lock.hasWaiters(Condition condition) 作用是查询是否有线程正在等待与此锁定有关的condition条件

1.5 isFair()、isHeldByCurrentThread()、isLocked()

lock.isFair() 判断是不是公平锁

lock.isHeldByCurrentThread() 作用是查询当前线程是否保持此锁定

lock.isLocked() 作用是查询此锁定是否由任意线程保持

1.6 lockInterruptibly()、tryLock()、tryLock(long timeout, TimeUnit unit)

lock.lockInterruptibly() 如果当前线程未中断,则获取锁定,如果已经被中断则出现异常

lock.tryLock() 仅在调用时锁定未被另一个线程保持的情况下,才获取该锁定

lock.tryLock(long, TimeUnit) 如果锁定在给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获取该锁定

1.7 awaitUninterriptibly()

class AwaitUninterruptibly {

public Lock lock = new ReentrantLock();

public Condition condition = lock.newCondition();

public void testMethod() {

try {

lock.lock();

System.out.println("await...begin");

condition.await();

System.out.println("await...end");

} finally {

lock.unlock();

}

}

}

public static void main(String[] args) {

try {

AwaitUninterruptibly awaitUninterruptibly = new AwaitUninterruptibly();

Thread t = new Thread() {

@Override

public void run() {

awaitUninterruptibly.testMethod();

}

};

t.start();

Thread.sleep(2000);

t.interrupt();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

在await状态中interrupt()会报错

//await...begin

java.lang.InterruptedException

at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.reportInterruptAfterWait(AbstractQueuedSynchronizer.java:2014)

at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2048)

at com.websocket.service.AwaitUninterruptibly.testMethod(LockTest.java:112)

at com.websocket.service.LockTest$1.run(LockTest.java:18)

改为condition.awaitUninterriptibly() 后,不会报错,程序不会停止

//await...begin

1.8 awaitUntil()

condition.awaitUntil(Date deadLine) 在等待时间到达后自动唤醒;在等待时间到达前,可以被其他线程提前唤醒

2. ReentrantReadWriterLock 类

类ReentrantLock具有完全互斥排他的效果,即同一时间只有一个线程在执行ReentrantLock.lock()方法后面的任务。这样做虽然保证了实例变量的线程安全性,但效率确实非常低下的。所以JDK中提供了一种读写锁ReentrantReadWriterLock 类,使用它可以加快运行效率,在某些不需要操作实例变量的方法中,完全可以使用读写锁ReentrantReadWriterLock来提升该方法的代码运行速度。

一个是读操作相关的锁,也称为共享锁

另一个是写操作相关的锁,也叫排他锁

多个读锁之间不互斥,读锁与写锁互斥

在没有线程Thread进行写入操作时,进行读取操作的多个Thread都可以获取读锁

进行写入操作的Thread只有在获取写锁后才能进行写入操作

即多个Thread可以同时进行读取操作,但是同一时刻只允许一个Thread进行写入操作

ReentrantReadWriterLock lock = new ReentrantReadWriterLock();

...

lock.readLock().lock(); //获取读锁

... //允许多个线程同时进入lock()后面的代码

lock.readLock.unLock();

lock.writeLock().lock(); //获取写锁

... //同一时间只允许一个线程执行lock()后面的代码

lock.writeLock().unLock();

两个线程,一个lock,一个获取读锁,一个获取写锁,“读写”、"写读"都是互斥的。只要出现写操作,就是互斥的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值