首页 > 其他 > 详细

Lock的使用

时间:2019-06-26 16:36:30      阅读:116      评论:0      收藏:0      [点我收藏+]

+ ReentrantLock类的使用 
+ ReentrantReadWriteLock类的使用

1. 使用ReentrantLock类

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();
}

关键字synchronizedwait()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先进先出顺序。非公平锁是一种获取锁的抢占机制,是随机获得锁的。

Lock方法

  1. 方法int getHoldCount()的作用是查询当前线程保持此锁定的个数,也就是调用lock()方法的次数。
  2. 方法int getQueueLength()的作用是返回正在等待获取此锁定的线程估计数
  3. 方法int getWaitQueueLength(Condition condition)的作用是返回等待与此锁定相关的给定条件Condition的线程估计数。比如有5个线程,每个线程都执行了同一个condition对象的await()方法,则调用getWaitQueueLength(condition)方法返回的指为5.
  4. 方法boolean hasQueuedThread(Thread thread)的作用是查询指定的线程是否正在等待获取此锁定。
  5. 方法boolean hasQueuedThreads()的作用是差选是否有线程正在等待获取此锁定。
  6. 方法boolean hasWaiters(Condition condition)的作用是查询是否有线程正在等待与此锁定有关的condition条件。
  7. 方法boolean isFair()的作用是判断是不是公平锁。
  8. 方法boolean isHeldByCurrentThread()的作用是查询当前线程是否保持此锁定。
  9. 方法boolean isLocked()的作用是查询此锁定是否由任意线程保持。
  10. 方法void lockInterruptibly()的作用是:如果当前线程未被中断,则获取锁定;如果已经被中断则抛出异常(java.lang.InterruptedException).
  11. 方法boolean tryLock()的作用是:仅在调用时锁未被另外线程保持的情况下,才获取此锁定。
  12. 方法boolean tryLock(long timeout,TimeUnit unit)的作用是:如果锁定在给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获取该锁定。
使用Condition对象可以对线程执行的业务进行排序规划

2. 使用ReentrantReadWriteLock类

读写锁有两个锁:一个是读操作相关的锁,也称为共享锁;一个是写操作相关的锁,也称为排他锁

多个读锁之间不互斥;读锁与写锁互斥;写锁与写锁互斥。
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();
    }
}

运行结果如下:
技术分享图片

Lock的使用

原文:https://www.cnblogs.com/Java-Script/p/11090619.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!