Lock接口出现的背景:
- synchronized的缺陷:
1、阻塞式:当某一个线程获取锁时,并执行该代码块,其他线程只能够一直等待,等待取锁的线程释放锁;
2、效率底:一但线程执行sleep,其他线程只能干巴巴的等待,一旦大量并发进入,将会极大影响性能;
3、释放锁:只有两种情况:a.当前线程执行完毕。 b.线程执行异常,JVM自动释放锁;- Lock锁的优势:
1、Lock 是一个类,通过这个类可以实现同步访问;
2、Lock 为非内置锁,可根据具体业务控制,但必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。
ReentrantLock
ReentrantLock是唯一实现Lock接口类,又名:并发锁、尝试锁、定时锁,以下是ReentrantLock的具体使用:
package com.cn.seesun2012.demo;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 并发锁 示例
* @author csdn:seesun2012
**/
public class TestLock {
// 定义全局变量(如果是局部将不起作用)
private Lock lock = new ReentranLock();
// 普通锁
public String testLock() {
// 阻塞,其他线程一直处于等待,直到当前线程释放锁
lock.lock();
try {
// 业务代码...
}catch(Exception ex){
// 异常处理...
}finally{
// 释放锁...
lock.unlock();
}
}
// 尝试锁
public String testTryLock(){
try {
// 不等待,尝试过没有获取到锁就直接返回false
if(lock.tryLock()) {
// 业务代码...
} else {
// 没有获取到锁,做其他事情...
}
} catch (Exception e) {
// 异常处理...
} finally {
// 释放锁...
lock.unlock();
}
}
// 尝试 + 定时 锁
public String testTimeTryLock(){
try {
// 等待,如果没有获取锁等待3秒,SECONDS代表:秒,3秒后仍然没有获取返回false
if(lock.tryLock(3, TimeUnit.SECONDS)) {
// 业务代码...
Thread.sleep(2l); // 模拟访问数据库
} else{
// 没有获取到锁,做其他事情...
}
} catch (Exception e) {
// 异常处理...
} finally {
// 释放锁...
lock.unlock();
}
}
// 测试启动程序
public static void main(String[] args) {
final TestLock testLock= new TestLock();
new Thread(){
public void run() {
testLock.testTimeTryLock(Thread.currentThread());
};
}.start();
new Thread(){
public void run() {
testLock.testTimeTryLock(Thread.currentThread());
};
}.start();
}
}
这样就是正确地使用Lock的方法了。
缺点:
- 不适用于分布式
注:以上内容仅提供参考和交流,请勿用于商业用途,如有侵权联系本人删除!
持续更新中…
如有对思路不清晰或有更好的解决思路,欢迎与本人交流,QQ群:273557553,个人微信:
你遇到的问题是小编创作灵感的来源!