论wait跟notify的正确使用方法-简单锁的实现
论wait和notify的正确使用方法-简单锁的实现
在java中实现某段代码在多个线程中互斥地执行,我们常常用到synchronized同步方法块,那么有什么东西可以代替它呢,就是j.u.c包中的Lock相关的类,该篇讲的是Lock的简单实现。
首先明确Lock的使用方法
Lock lock = new Lock(); try{ lock.lock(); /********需要互斥的代码**********/ }finally{ lock.unlock(); }
需要注意的是多个线程中的lock对象必须是同一个,要不然起不到互斥的作用。
lock()和unLock()必须成对出现,且unLock()需要放在finally中,避免出现异常造成的死锁
如果在其他线程unLock(),就应该抛出IllegalMonitorStateException.
实现思路如下:
1.为了保证lock和unLock的成双成对,我们需要记录lock的线程,然后和执行unLock的线程进行比较,如果是”李鬼“,就抛出异常。lock和unLock我们已经用synchronized保证是”原子操作“了
public class Lock { private Thread lockedTh = null; public synchronized void lock(){ lockedTh =Thread.currentThread(); } public synchronized void unLock(){ if(lockedTh!=Thread.currentThread()){ throw new IllegalMonitorStateException(); } lockedTh = null; } }
2.执行Lock之后,其他线程就必须等着,执行unLock之后,就该喊一个线程起来,于是
public class Lock { private Thread lockedTh = null; public synchronized void lock() throws InterruptedException{ wait(); lockedTh =Thread.currentThread(); } public synchronized void unLock(){ if(lockedTh!=Thread.currentThread()){ throw new IllegalMonitorStateException(); } notify(); lockedTh = null; } }
3.上面的版本第一个执行lock的线程也会堵着,所以我们设置一个标志符,如果现在没有锁住,就可以进来,同时改变标志。反之就等着,直到可以进来,所以最终版本是
package com.cici.lock; /** * @author 尹定宇 * @Email 768166775@qq.com * @version 2013-7-14 下午6:48:18 * @info */ public class Lock { private boolean isLocked = false; private Thread lockedTh = null; public synchronized void lock() throws InterruptedException{ while(isLocked){ wait(); } lockedTh =Thread.currentThread(); isLocked = true; } public synchronized void unLock(){ if(lockedTh!=Thread.currentThread()){ throw new IllegalMonitorStateException(); } notify(); isLocked = false; lockedTh = null; } }