使用synchronized实现一个Lock
刚看到这个题目的时候无从下手,因为觉得synchronized和lock在加锁的方式上有很大不同,比如,看看正常情况下synchronized时如何加锁的。
方式一:
- public synchronized void a(){
- //TODO
- }
方式二:
- public void b(){
- synchronized(this){
- //TODO
- }
- }
从这两种方式来看,锁都是加在{}之间的,我们再来看看Lock是如何做的呢:
- public void c() {
- lock.lock();
- try {
- // TODO
- } finally {
- lock.unlock();
- }
- }
这种方式的锁是加在lock() 和unlock()之间的,所以要想实现一个lock功能,就要想怎么实现这样两个方法,lock()和unlock()方法,先定义一个框架如下所示:
- public void lock(){
- }
- public void unlock(){
- }
然后要想怎么用synchronized去实现这两个方法。
现在其实只是稍微清楚了一点思路,但是还不知道怎么去填充这两个方法,这是后再来分析一下Lock的加锁有什么特点,再来看看这段代码:
- 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()的时候是有一个条件的,想想我们应该使用什么作为条件呢?
我们应该使用当前锁是否被占用作为判断条件,如果锁被占用,current thread等待,想想我们在使用synchronized的时候是不是一直使用的这个条件,答案也是肯定的。
再来分析一下什么时候释放锁,使用什么作为条件,想想如果线程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;
- private boolean isLooked() {
- return 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.isLooked()) {
- System.out.println(String.format("thread %s is waitting lock", currentThreadId));
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- owner = currentThreadId;
- System.out.println(String.format("Lock is acquired by thread %s", owner));
- }
- public synchronized void unlock() {
- if (!this.isLooked() || owner != Thread.currentThread().getId()) {
- throw new IllegalStateException("Only Lock owner can unlock the lock");
- }
- System.out.println(String.format("thread %s is unlocking", owner));
- System.out.println();
- owner = NONE;
- notify();
- }
- public static void main(String[] args) {
- 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) {
- return new Thread(group, r);
- }
- });
- for (int i = 0; i < 20; i++) {
- executor.submit(new Runnable() {
- @Override
- public void run() {
- lock.lock();
- System.out.println(String.format("thread %s is running...", Thread.currentThread().getId()));
- try {
- Thread.sleep(new Random().nextInt(1000));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- lock.unlock();
- }
- });
- }
- }
- }
运行一下看看结果:
- Lock is acquired by thread 8
- thread 8 is running...
- thread 27 is waitting lock
- thread 26 is waitting lock
- thread 25 is waitting lock
- thread 24 is waitting lock
- thread 23 is waitting lock
- thread 22 is waitting lock
- thread 21 is waitting lock
- thread 20 is waitting lock
- thread 19 is waitting lock
- thread 18 is waitting lock
- thread 17 is waitting lock
- thread 16 is waitting lock
- thread 15 is waitting lock
- thread 14 is waitting lock
- thread 13 is waitting lock
- thread 12 is waitting lock
- thread 11 is waitting lock
- thread 10 is waitting lock
- thread 9 is waitting lock
- thread 8 is unlocking
- Lock is acquired by thread 27
- thread 27 is running...
- thread 27 is unlocking
- Lock is acquired by thread 26
- thread 26 is running...
- thread 26 is unlocking
- Lock is acquired by thread 25
- thread 25 is running...
- thread 25 is unlocking
- Lock is acquired by thread 24
- thread 24 is running...
- thread 24 is unlocking
- Lock is acquired by thread 23
- thread 23 is running...
- thread 23 is unlocking
- Lock is acquired by thread 22
- thread 22 is running...
- thread 22 is unlocking
- Lock is acquired by thread 21
- thread 21 is running...
- thread 21 is unlocking
- Lock is acquired by thread 20
- thread 20 is running...
- thread 20 is unlocking
- Lock is acquired by thread 19
- thread 19 is running...
- thread 19 is unlocking
- Lock is acquired by thread 18
- thread 18 is running...
- thread 18 is unlocking
- Lock is acquired by thread 17
- thread 17 is running...
- thread 17 is unlocking
- Lock is acquired by thread 16
- thread 16 is running...
- thread 16 is unlocking
- Lock is acquired by thread 15
- thread 15 is running...
- thread 15 is unlocking
- Lock is acquired by thread 14
- thread 14 is running...
- thread 14 is unlocking
- Lock is acquired by thread 13
- thread 13 is running...
- thread 13 is unlocking
- Lock is acquired by thread 12
- thread 12 is running...
- thread 12 is unlocking
- Lock is acquired by thread 11
- thread 11 is running...
- thread 11 is unlocking
- Lock is acquired by thread 10
- thread 10 is running...
- thread 10 is unlocking
- Lock is acquired by thread 9
- thread 9 is running...
- thread 9 is unlocking
如果把for循环改成30次,再看一下结果:
- Lock is acquired by thread 8
- thread 8 is running...
- thread 27 is waitting lock
- thread 26 is waitting lock
- thread 25 is waitting lock
- thread 24 is waitting lock
- thread 23 is waitting lock
- thread 22 is waitting lock
- thread 21 is waitting lock
- thread 20 is waitting lock
- thread 19 is waitting lock
- thread 18 is waitting lock
- thread 17 is waitting lock
- thread 16 is waitting lock
- thread 15 is waitting lock
- thread 14 is waitting lock
- thread 13 is waitting lock
- thread 12 is waitting lock
- thread 11 is waitting lock
- thread 10 is waitting lock
- thread 9 is waitting lock
- thread 8 is unlocking
- Lock is acquired by thread 27
- thread 27 is running...
- thread 8 is waitting lock
- thread 27 is unlocking
- Lock is acquired by thread 27
- thread 27 is running...
- thread 26 is waitting lock
- thread 27 is unlocking
- Lock is acquired by thread 27
- thread 27 is running...
- thread 25 is waitting lock
- thread 27 is unlocking
- Lock is acquired by thread 24
- thread 24 is running...
- thread 27 is waitting lock
- thread 24 is unlocking
- Lock is acquired by thread 23
- thread 23 is running...
- thread 24 is waitting lock
- thread 23 is unlocking
- Lock is acquired by thread 22
- thread 22 is running...
- thread 23 is waitting lock
- thread 22 is unlocking
- Lock is acquired by thread 22
- thread 22 is running...
- thread 21 is waitting lock
- thread 22 is unlocking
- Lock is acquired by thread 22
- thread 22 is running...
- thread 20 is waitting lock
- thread 22 is unlocking
- Lock is acquired by thread 22
- thread 22 is running...
- thread 19 is waitting lock
- thread 22 is unlocking
- Lock is acquired by thread 22
- thread 22 is running...
- thread 18 is waitting lock
- thread 22 is unlocking
- Lock is acquired by thread 17
- thread 17 is running...
- thread 17 is unlocking
- Lock is acquired by thread 16
- thread 16 is running...
- thread 16 is unlocking
- Lock is acquired by thread 15
- thread 15 is running...
- thread 15 is unlocking
- Lock is acquired by thread 14
- thread 14 is running...
- thread 14 is unlocking
- Lock is acquired by thread 13
- thread 13 is running...
- thread 13 is unlocking
- Lock is acquired by thread 12
- thread 12 is running...
- thread 12 is unlocking
- Lock is acquired by thread 11
- thread 11 is running...
- thread 11 is unlocking
- Lock is acquired by thread 10
- thread 10 is running...
- thread 10 is unlocking
- Lock is acquired by thread 9
- thread 9 is running...
- thread 9 is unlocking
- Lock is acquired by thread 8
- thread 8 is running...
- thread 8 is unlocking
- Lock is acquired by thread 26
- thread 26 is running...
- thread 26 is unlocking
- Lock is acquired by thread 25
- thread 25 is running...
- thread 25 is unlocking
- Lock is acquired by thread 27
- thread 27 is running...
- thread 27 is unlocking
- Lock is acquired by thread 24
- thread 24 is running...
- thread 24 is unlocking
- Lock is acquired by thread 23
- thread 23 is running...
- thread 23 is unlocking
- Lock is acquired by thread 21
- thread 21 is running...
- thread 21 is unlocking
- Lock is acquired by thread 20
- thread 20 is running...
- thread 20 is unlocking
- Lock is acquired by thread 19
- thread 19 is running...
- thread 19 is unlocking
- Lock is acquired by thread 18
- thread 18 is running...
- thread 18 is unlocking

浙公网安备 33010602011771号