由于synchronized关键字锁对象的添加与释放我们并不明确,java为我们提供了一个Lock接口
Lock接口源自JDK5,其有三个直接实现类,分别是 :
ReentrantLock,ReentrantReadWriteLock.ReadLock,ReentrantReadWriteLock.WriteLock
其中后两个是ReentrantReadWriteLock的嵌套类
方法
1 2 3 4 5 6 7
| void lock(); void unlock(); void lockInterruptibly(); Condition newCondition(); boolean tryLock(); boolean tryLock(long time, TimeUnit unit);
|
简单案例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| Runnable ticket = new Runnable() { private int ticket = 100; Lock lock = new ReentrantLock(); @Override public void run() { while (ticket > 0){ lock.lock(); if (ticket > 0) System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket-- + "张票!"); lock.unlock(); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } }; Thread thread1 = new Thread(ticket,"窗口1"); Thread thread2 = new Thread(ticket,"窗口2"); Thread thread3 = new Thread(ticket,"窗口3"); thread1.start(); thread2.start(); thread3.start();
|
执行结果如下 :

出现异常锁资源释放问题
由于需要程序调用unlock()方法来释放锁资源,那么如果在释放之前出现异常呢?
改动如下 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| if (ticket > 0) System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket-- + "张票!"); if (Thread.currentThread().getName().equals("窗口1") && ticket < 80) System.out.println(10 / 0); lock.unlock(); ... thread1.start(); thread2.start(); thread3.start(); try { thread1.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(thread1.isAlive());
|
可以看到,由于"窗口1"被异常终止且没有释放锁,其他两个线程一直在等待锁
结果如下 :

使用Lock实现类做同步的处理,一定要记得处理锁对象的释放问题
用try-catch-finally处理释放问题
改进如下 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| while (ticket > 0){ try { lock.lock(); if (ticket > 0) System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket-- + "张票!"); if (Thread.currentThread().getName().equals("窗口1") && ticket < 80) System.out.println(10 / 0); } catch (Exception e) { e.printStackTrace(); break; }finally { lock.unlock(); } try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } }
|
执行结果如下 :
