1.分析Java中常用的锁时sychronized关键字锁,它包含了三类
// 关键字在实例方法上,锁为当前实例 public synchronized void instanceLock() { // code } // 关键字在静态方法上,锁为当前Class对象 public static synchronized void classLock() { // code } // 关键字在代码块上,锁为括号里面的对象 public void blockLock() { Object o = new Object(); synchronized (o) { // code } }2.今天的主题是介绍显示锁Lock
Lock锁怎么使用呢,我们通过try-finally的方式来获取锁和释放锁
try{ captured=lock.tryLock(); }finally{ if(captured){ lock.unlock(); } }那么我为什么要用显示锁Lock呢???
在synchronized中,如果某些事物失败了就会直接抛出异常,但是没有办法去保证程序继续运行
但是使用lock锁的时候,在finally中都是要释放锁的,保证了程序的完整性运行.
哪些情况下用显示lock锁呢:
(1)当时用synchronized关键字不能尝试着获取锁,且最终获取锁会失败,
(2)尝试着获取锁一段时间,然后放弃它.
简单介绍一下显示锁的2个方法
boolean flat= lock.tryLock();仅在调用的时候锁未被另一个线程保持的时候才会获取锁,如果锁被另一个线程占用,则返回false
如果锁已经被当前线程保证,那么将保持计数加1
boolean flat= lock.tryLock(long timeout, TimeUnit unit);延迟指定时间或尝试获取锁,
来一个简单的实例:
import java.util.concurrent.*; import java.util.concurrent.locks.*; public class AttemptLocking { private ReentrantLock lock=new ReentrantLock(); public void untimed(){ boolean captured=lock.tryLock(); try{ System.out.println("trylock():"+captured); //captured=lock.tryLock(); //System.out.println(captured); }finally{ if(captured){ lock.unlock(); } } } public void timed(){ boolean captured=false; try{ captured=lock.tryLock(2,TimeUnit.SECONDS); }catch(InterruptedException e){ throw new RuntimeException(e); } try{ System.out.println("tryLock(2, TimeUnit.SECONDS"+ captured); }finally{ if(captured){ lock.unlock(); } } } public static void main(String[] args)throws Exception{ final AttemptLocking al=new AttemptLocking(); al.untimed(); al.timed(); new Thread(){ {setDaemon(true);} public void run(){ al.lock.lock(); System.out.println("acquired"); } }.start(); Thread.sleep(100);//保证后台现在运行 al.untimed(); al.timed(); } }运行结果
我们可以看到当锁被后台线程占有的时候,主线程就处于阻塞状态,
我们来试一试如果当前线程连续获取2次锁,只释放一次锁,那么后台线程还会获取锁吗,
import java.util.concurrent.*; import java.util.concurrent.locks.*; public class AttemptLocking { private ReentrantLock lock=new ReentrantLock(); public void untimed(){ boolean captured=lock.tryLock(); try{ System.out.println("trylock():"+captured); captured=lock.tryLock(); //System.out.println(captured); }finally{ if(captured){ lock.unlock(); } } } public void timed(){ boolean captured=false; try{ captured=lock.tryLock(2,TimeUnit.SECONDS); }catch(InterruptedException e){ throw new RuntimeException(e); } try{ System.out.println("tryLock(2, TimeUnit.SECONDS"+ captured); }finally{ if(captured){ lock.unlock(); } } } public static void main(String[] args)throws Exception{ final AttemptLocking al=new AttemptLocking(); al.untimed(); al.timed(); new Thread(){ {setDaemon(true);} public void run(){ al.lock.lock(); System.out.println("acquired"); } }.start(); Thread.sleep(100);//保证后台现在运行 al.untimed(); al.timed(); } }结果显而易见,后台线程获取锁是失败的,
,嘿嘿,当我们在主线程中尝试了2次加锁,然后再进行2次释放锁,后台线程就获取了锁.尝试一下吧.