使用synchronized实现一个Lock代码详解
刚看到这个题目的时候无从下手,因为觉得synchronized和lock在加锁的方式上有很大不同,比如,看看正常情况下synchronized时如何加锁的。
方式一:
publicsynchronizedvoida(){ //TODO }
方式二:
publicvoidb(){ synchronized(this){ //TODO } }
从这两种方式来看,锁都是加在{}之间的,我们再来看看Lock是如何做的呢:
publicvoidc(){ lock.lock(); try{ //TODO }finally{ lock.unlock(); } }
这种方式的锁是加在lock()和unlock()之间的,所以要想实现一个lock功能,就要想怎么实现这样两个方法,lock()和unlock()方法,先定义一个框架如下所示:
publicvoidlock(){ } publicvoidunlock(){ }
然后要想怎么用synchronized去实现这两个方法。
现在其实只是稍微清楚了一点思路,但是还不知道怎么去填充这两个方法,这是后再来分析一下Lock的加锁有什么特点,再来看看这段代码:
publicvoidc(){ lock.lock(); //Whencurrentthreadgetthelock,otherthreadhastowait try{ //currentthreadgetinthelock,otherthreadcannotgetin //TODO } finally{ lock.unlock(); //currentthreadreleasethelock } }
这段代码我只是加了一点注释,别的什么都没有做,是不是帮助理解这段代码,看看出现频率最高的词是什么,是currentthread,那么我们去填充lock()和unlock()方法的时候是不是注意要抓住currentthread这个关键字就可以找到解决方案呢?答案是肯定的。
接着分析,使用synchronized的时候如何让线程等待呢?是用wait()方法。怎么让线程唤醒呢,是用notify()方法。那么就要在lock()方法中使用wait()方法,在unlock()方法中使用notify()方法。那么我们在使用wait()和notify()的时候是有一个条件的,想想我们应该使用什么作为条件呢?
我们应该使用当前锁是否被占用作为判断条件,如果锁被占用,currentthread等待,想想我们在使用synchronized的时候是不是一直使用的这个条件,答案也是肯定的。
再来分析一下什么时候释放锁,使用什么作为条件,想想如果线程A拿到了锁,线程B能释放吗?当然不能,如果B能释放就违反了原则,当然不能。肯定是A线程的锁只能A来释放。所以判断条件就是判断持有锁的线程是不是currentthread,如果是的话,可以释放,不是的话当然不能。
现在来看看完整的代码:
packagetest.lock; importjava.util.Random; importjava.util.concurrent.ExecutorService; importjava.util.concurrent.Executors; importjava.util.concurrent.ThreadFactory; publicclassNaiveLock{ privatestaticfinallongNONE=-1; privatelongowner=NONE; privateBooleanisLooked(){ returnowner!=NONE; } publicsynchronizedvoidlock(){ longcurrentThreadId=Thread.currentThread().getId(); if(owner==currentThreadId){ thrownewIllegalStateException("Lockhasbeenacquiredbycurrentthread"); } while(this.isLooked()){ System.out.println(String.format("thread%siswaittinglock",currentThreadId)); try{ wait(); } catch(InterruptedExceptione){ e.printStackTrace(); } } owner=currentThreadId; System.out.println(String.format("Lockisacquiredbythread%s",owner)); } publicsynchronizedvoidunlock(){ if(!this.isLooked()||owner!=Thread.currentThread().getId()){ thrownewIllegalStateException("OnlyLockownercanunlockthelock"); } System.out.println(String.format("thread%sisunlocking",owner)); System.out.println(); owner=NONE; notify(); } publicstaticvoidmain(String[]args){ finalNaiveLocklock=newNaiveLock(); ExecutorServiceexecutor=Executors.newFixedThreadPool(20,newThreadFactory(){ privateThreadGroupgroup=newThreadGroup("testthreadgroup"); { group.setDaemon(true); } @Override publicThreadnewThread(Runnabler){ returnnewThread(group,r); } } ); for(inti=0;i<20;i++){ executor.submit(newRunnable(){ @Override publicvoidrun(){ lock.lock(); System.out.println(String.format("thread%sisrunning...",Thread.currentThread().getId())); try{ Thread.sleep(newRandom().nextint(1000)); } catch(InterruptedExceptione){ e.printStackTrace(); } lock.unlock(); } } ); } } }
运行一下看看结果:
Lockisacquiredbythread8 thread8isrunning... thread27iswaittinglock thread26iswaittinglock thread25iswaittinglock thread24iswaittinglock thread23iswaittinglock thread22iswaittinglock thread21iswaittinglock thread20iswaittinglock thread19iswaittinglock thread18iswaittinglock thread17iswaittinglock thread16iswaittinglock thread15iswaittinglock thread14iswaittinglock thread13iswaittinglock thread12iswaittinglock thread11iswaittinglock thread10iswaittinglock thread9iswaittinglock thread8isunlocking Lockisacquiredbythread27 thread27isrunning... thread27isunlocking Lockisacquiredbythread26 thread26isrunning... thread26isunlocking Lockisacquiredbythread25 thread25isrunning... thread25isunlocking Lockisacquiredbythread24 thread24isrunning... thread24isunlocking Lockisacquiredbythread23 thread23isrunning... thread23isunlocking Lockisacquiredbythread22 thread22isrunning... thread22isunlocking Lockisacquiredbythread21 thread21isrunning... thread21isunlocking Lockisacquiredbythread20 thread20isrunning... thread20isunlocking Lockisacquiredbythread19 thread19isrunning... thread19isunlocking Lockisacquiredbythread18 thread18isrunning... thread18isunlocking Lockisacquiredbythread17 thread17isrunning... thread17isunlocking Lockisacquiredbythread16 thread16isrunning... thread16isunlocking Lockisacquiredbythread15 thread15isrunning... thread15isunlocking Lockisacquiredbythread14 thread14isrunning... thread14isunlocking Lockisacquiredbythread13 thread13isrunning... thread13isunlocking Lockisacquiredbythread12 thread12isrunning... thread12isunlocking Lockisacquiredbythread11 thread11isrunning... thread11isunlocking Lockisacquiredbythread10 thread10isrunning... thread10isunlocking Lockisacquiredbythread9 thread9isrunning... thread9isunlocking
如果把for循环改成30次,再看一下结果:
Lockisacquiredbythread8 thread8isrunning... thread27iswaittinglock thread26iswaittinglock thread25iswaittinglock thread24iswaittinglock thread23iswaittinglock thread22iswaittinglock thread21iswaittinglock thread20iswaittinglock thread19iswaittinglock thread18iswaittinglock thread17iswaittinglock thread16iswaittinglock thread15iswaittinglock thread14iswaittinglock thread13iswaittinglock thread12iswaittinglock thread11iswaittinglock thread10iswaittinglock thread9iswaittinglock thread8isunlocking Lockisacquiredbythread27 thread27isrunning... thread8iswaittinglock thread27isunlocking Lockisacquiredbythread27 thread27isrunning... thread26iswaittinglock thread27isunlocking Lockisacquiredbythread27 thread27isrunning... thread25iswaittinglock thread27isunlocking Lockisacquiredbythread24 thread24isrunning... thread27iswaittinglock thread24isunlocking Lockisacquiredbythread23 thread23isrunning... thread24iswaittinglock thread23isunlocking Lockisacquiredbythread22 thread22isrunning... thread23iswaittinglock thread22isunlocking Lockisacquiredbythread22 thread22isrunning... thread21iswaittinglock thread22isunlocking Lockisacquiredbythread22 thread22isrunning... thread20iswaittinglock thread22isunlocking Lockisacquiredbythread22 thread22isrunning... thread19iswaittinglock thread22isunlocking Lockisacquiredbythread22 thread22isrunning... thread18iswaittinglock thread22isunlocking Lockisacquiredbythread17 thread17isrunning... thread17isunlocking Lockisacquiredbythread16 thread16isrunning... thread16isunlocking Lockisacquiredbythread15 thread15isrunning... thread15isunlocking Lockisacquiredbythread14 thread14isrunning... thread14isunlocking Lockisacquiredbythread13 thread13isrunning... thread13isunlocking Lockisacquiredbythread12 thread12isrunning... thread12isunlocking Lockisacquiredbythread11 thread11isrunning... thread11isunlocking Lockisacquiredbythread10 thread10isrunning... thread10isunlocking Lockisacquiredbythread9 thread9isrunning... thread9isunlocking Lockisacquiredbythread8 thread8isrunning... thread8isunlocking Lockisacquiredbythread26 thread26isrunning... thread26isunlocking Lockisacquiredbythread25 thread25isrunning... thread25isunlocking Lockisacquiredbythread27 thread27isrunning... thread27isunlocking Lockisacquiredbythread24 thread24isrunning... thread24isunlocking Lockisacquiredbythread23 thread23isrunning... thread23isunlocking Lockisacquiredbythread21 thread21isrunning... thread21isunlocking Lockisacquiredbythread20 thread20isrunning... thread20isunlocking Lockisacquiredbythread19 thread19isrunning... thread19isunlocking Lockisacquiredbythread18 thread18isrunning... thread18isunlocking
总结
以上就是本文关于使用synchronized实现一个Lock代码详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:
Java线程同步Lock同步锁代码示例
Java编程synchronized与lock的区别【推荐】
Java多线程之readwritelock读写分离的实现代码
如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!