使用synchronized写一个显示锁

public interface MyLock {
    
    void lock () throws InterruptedException;
    
    void lock(long millis) throws TimeoutException , InterruptedException ,ParametersIllegalException;
    
    void unlock();
    
    class TimeoutException  extends Exception{
        
        TimeoutException(String msg){
            super(msg);
        }
        private static final long serialVersionUID = 1L;
    }
    
    class ParametersIllegalException  extends Exception{
        
        ParametersIllegalException(String msg){
            super(msg);
        }
        private static final long serialVersionUID = 1L;
    }
}

 

public class MyLockImpl  implements MyLock{

    private boolean  initValue; // false表示monitor没有被占用
    
    private Thread currentThread;
    
    @Override
    public  synchronized void lock() throws InterruptedException {
        while(initValue) {//monitor被占用
            this.wait();
        }
        initValue = true;
        currentThread = Thread.currentThread();
    }

    @Override
    public synchronized void unlock() {
        if(currentThread == Thread.currentThread()) {
            System.out.println(""+Thread.currentThread().getName()+"" + " release the monitor");
            initValue = false;
            this.notifyAll();
        }
    }

    @Override
    public  synchronized void lock(long millis) throws TimeoutException, InterruptedException, ParametersIllegalException {
            if (millis <= 0) 
               throw new ParametersIllegalException("parameters illegal");
            long hasRemaining = millis;
            long endTime = System.currentTimeMillis() + millis;
            while (initValue) {
                if (hasRemaining <= 0)
                    throw new TimeoutException("Time out");
                this.wait(millis);
                hasRemaining = endTime - System.currentTimeMillis();
            }
            this.initValue = true;
            this.currentThread = Thread.currentThread();
    }
    

}
public class MyLockTest {
    
    public static void main(String[] args) {
        MyLock myLock = new MyLockImpl();
        
        Stream.of("T1","T2","T3","T4").forEach(name -> 
            new Thread(()-> {
                try {
                    myLock.lock(10);
                    System.out.println(""+Thread.currentThread().getName()+"" +" get the monitor");
                    m1();
                } catch (InterruptedException  e) {
                    e.printStackTrace();
                } catch (TimeoutException e) {
                    System.out.println(""+Thread.currentThread().getName()+"" +" timeout");
                } catch (ParametersIllegalException e) {
                    System.out.println(""+Thread.currentThread().getName()+"" +" parameter illegal");
                    //e.printStackTrace();
                }finally {
                    myLock.unlock();
                }
            },name).start()
        );
    }
    
    
    public static void m1() throws InterruptedException {
        System.out.println(""+Thread.currentThread().getName()+"" + "is working ...");
        Thread.sleep(3_000);
    }

}

 

注意wait方法可能存在spurious(假的)唤醒,wait方法应该在一个循环中使用

 

 

posted @ 2019-04-16 14:26  踏月而来  阅读(198)  评论(0编辑  收藏  举报