剛看到這個題目的時候無從下手,由於以爲synchronized和lock在加鎖的方式上有很大不一樣,好比,看看正常狀況下synchronized時如何加鎖的。java
方式一: 框架
public synchronized void a(){ //TODO }
方式二: dom
public void b(){ synchronized(this){ //TODO } }
從這兩種方式來看,鎖都是加在{}之間的,咱們再來看看Lock是如何作的呢: ide
public void c() { lock.lock(); try { // TODO } finally { lock.unlock(); } }
這種方式的鎖是加在lock() 和unlock()之間的,因此要想實現一個lock功能,就要想怎麼實現這樣兩個方法,lock()和unlock()方法,先定義一個框架以下所示: ui
public void lock(){ } public void unlock(){ }
而後要想怎麼用synchronized去實現這兩個方法。 this
如今其實只是稍微清楚了一點思路,可是還不知道怎麼去填充這兩個方法,這是後再來分析一下Lock的加鎖有什麼特色,再來看看這段代碼:spa
public void c() { lock.lock();//When current thread get the lock, other thread has to wait try { //current thread get in the lock, other thread can not get in // TODO } finally { lock.unlock();//current thread release the lock } }
這段代碼我只是加了一點註釋,別的什麼都沒有作,是否是幫助理解這段代碼,看看出現頻率最高的詞是什麼,是current thread,那麼咱們去填充lock()和unlock()方法的時候是否是注意要抓住current thread這個關鍵字就能夠找到解決方案呢?答案是確定的。 線程
接着分析,使用synchronized的時候如何讓線程等待呢?是用wait()方法。怎麼讓線程喚醒呢,是用notify()方法。那麼就要在lock()方法中使用wait()方法,在unlock()方法中使用notify()方法。那麼咱們在使用wait()和notify()的時候是有一個條件的,想一想咱們應該使用什麼做爲條件呢?code
咱們應該使用當前鎖是否被佔用做爲判斷條件,若是鎖被佔用,current thread等待,想一想咱們在使用synchronized的時候是否是一直使用的這個條件,答案也是確定的。orm
再來分析一下何時釋放鎖,使用什麼做爲條件,想一想若是線程A拿到了鎖,線程B能釋放嗎?固然不能,若是B能釋放就違反了原則,固然不能。確定是A線程的鎖只能A來釋放。因此判斷條件就是判斷持有鎖的線程是否是current thread,若是是的話,能夠釋放,不是的話固然不能。
如今來看看完整的代碼:網上寫的有點亂,我本身重新整理了一下,而且能夠正常運行
package test_lock; import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; public class NaiveLock { private static final long NONE=-1; private long owner =NONE; public synchronized void lock(){ long currentThreadId=Thread.currentThread().getId(); if(owner==currentThreadId){ throw new IllegalStateException("lock has been acquired by current thread"); } while(this.owner!=NONE){ System.out.println(String.format("thread %s is waiting lock", currentThreadId)); try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.owner=currentThreadId; System.out.println(String.format("lock is acquired by thread %s", currentThreadId)); } public synchronized void unlock(){ long currentThreadId=Thread.currentThread().getId(); if(this.owner!=currentThreadId){ throw new IllegalStateException("Only lock owner can unlock the lock"); } System.out.println(String.format("thread %s is unlocking", owner)); owner=NONE; notify(); } public static void main(String[] args) { // TODO Auto-generated method stub final NaiveLock lock=new NaiveLock(); ExecutorService executor= Executors.newFixedThreadPool(20, new ThreadFactory(){ private ThreadGroup group =new ThreadGroup("test thread group"); { group.setDaemon(true); } @Override public Thread newThread(Runnable r) { // TODO Auto-generated method stub return new Thread(group,r); }}); for(int i=0;i<20;i++){ executor.submit(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub lock.lock(); System.out.println(String.format("thread %s is running...", Thread.currentThread().getId())); try { Thread.sleep(new Random().nextInt(1000)); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } lock.unlock(); }}); } } }
結果爲:
lock is acquired by thread 10 thread 10 is running... thread 29 is waiting lock
....
thread 13 is running... thread 13 is unlocking lock is acquired by thread 12 thread 12 is running... thread 12 is unlocking