又是一个基于AQS好用的类,看来下次有必要看看AQS了,正好又是放假。
既然叫显式锁,必然也有隐式锁,也就是所谓的synchronzied关键字,它们两者的区别呢在于使用范围,synchronzied关键字的使用范围比Lock要小,在Lock的实现类中与synchronzied相近似的类叫ReentrantLock,也叫可重入锁,待会儿在说看看Lock吧
Lock
是一个接口,主要的实现类有三个 ReadLock(写锁),WriteLock(读锁),ReentrantLock(可重入锁)
核心方法:
1、lock():获取锁并上锁。
2、unlock():释放锁,未释放会造成阻塞,一般放在程序的finally代码块中。
3、tryLock():尝试的获取锁,带参数的为超时尝试获取锁。
4、newCondition():获取到Condition接口的实现类,用于配合Lock实现等待通知功能,每调用一次就获取一个新的Condition,并非只有一个。
5、 lockInterruptibly():获取锁但是可以中断这个锁。
使用示例:
static Lock lock = new ReentrantLock();
static int count = 0;public static void main(String [] arg0){lock.lock();//获取锁try{count ++ ;}finally{lock.unlock();//释放锁}}
//该示例就做一个统计吧
可重入锁(ReentrantLock)
就是可以重复获取锁,但是这种一般出现于递归算法,重复获取了多少次锁就会释放多少次锁。
看一个案例:
static Lock lock = new ReentrantLock();static int count = 0;public synchronized static void addIntger() {count ++;while(count<10) {addIntger();//可重入锁}}public static void addLockIntger() {lock.lock();try {count ++;while(count<10) {addLockIntger();//可重入锁}} finally {lock.unlock();}}public static void main(String[] args) {System.out.println(count);addLockIntger();System.out.println(count);}
公平锁和非公平锁
公平锁(new FairSync()):即同一时刻去多个线程请求锁,先到先得,排队获取锁即为公平锁,未获取到锁的线程会被挂起(非阻塞等待,是会进入到AQS的尾队列等待,跟非公平锁比,耗时就是花费在这里),等到锁释放后按照顺序获取锁,所以与非公平锁相比,更耗时。
非公平锁(new NonfairSync()):即同一时刻多个线程去请求锁,不是按照先到先的顺序获取锁即为非公平锁,无需进入AQS队列等待,运行速度更快,创建Lock对象默认为非公平锁。
这两种锁都继承了AQS(不得不说Doug Lea大师的强大),公平锁适合在按顺序执行的场景。
读写锁(ReadWriteLock)
ReadWriteLock并没有继承Lock接口,而是在它的实现类中ReentrantReadWriteLock有两个内部类却继承了Lock接口,即为ReadLock和WriteLock,这两均实现了AQS抽象类。
这个种锁使用的场景为读多写少的场景,在获取写锁时,读写锁都会进入阻塞状态,而获取读锁并不会进入阻塞状态。
public interface ReadWriteLock {/*** Returns the lock used for reading.** @return the lock used for reading*/Lock readLock();/*** Returns the lock used for writing.** @return the lock used for writing*/Lock writeLock();
}
Condition
可以配合Lock使用等待通知模式,这里就不演示啦,与之前的wait()和notify/notifyAll()相近似,看一下这个接口中的方法定义:
1、await():类似于Object的wait()等待。
2、awaitUninterruptibly():这个表示等待不可中断,其他的等待都可以被中断。
3、awaitNanos(long):超时等待。
4、awaitUntil(Date):可指定时间超时等待,与上面几种超时方法差不多。
5、signal():类似与Object中的notify()。
6、signalAll():类似与Object中的notifyAll()。
LockSupport
是Lock的支持类,里面都是静态方法
主要是用来阻塞、唤醒一个线程
1、park():阻塞当前线程
2、unpark(Thread t):唤醒指定线程
park也有其他带参数的方法,基本都是不同形式的超时等待方法。
好啦差不多就这样了,Lock的用途还是挺广泛的,在很多开源包都能看见这个的身影,比如阿里的Druid连接池中就用到了。写的并不是很好,各路大佬可以在评论里面补充咯