使用synchronized实现一个Lock

刚看到这个题目的时候无从下手,因为觉得synchronized和lock在加锁的方式上有很大不同,比如,看看正常情况下synchronized时如何加锁的。

        方式一:

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. public synchronized void a(){  
  2.     //TODO  
  3. }  


        方式二:

 

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. public void b(){  
  2.     synchronized(this){  
  3.         //TODO  
  4.     }  
  5. }  


        从这两种方式来看,锁都是加在{}之间的,我们再来看看Lock是如何做的呢:

 

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. public void c() {  
  2.     lock.lock();  
  3.     try {  
  4.         // TODO  
  5.     } finally {  
  6.         lock.unlock();  
  7.     }  
  8. }  


        这种方式的锁是加在lock() 和unlock()之间的,所以要想实现一个lock功能,就要想怎么实现这样两个方法,lock()unlock()方法,先定义一个框架如下所示:

 

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. public void lock(){  
  2.       
  3. }  
  4.   
  5. public void unlock(){  
  6.       
  7. }  


        然后要想怎么用synchronized去实现这两个方法。

 

        现在其实只是稍微清楚了一点思路,但是还不知道怎么去填充这两个方法,这是后再来分析一下Lock的加锁有什么特点,再来看看这段代码:

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. public void c() {  
  2.     lock.lock();//When current thread get the lock, other thread has to wait  
  3.     try {  
  4.         //current thread get in the lock, other thread can not get in  
  5.         // TODO  
  6.     } finally {  
  7.         lock.unlock();//current thread release the lock  
  8.     }  
  9. }  


        这段代码我只是加了一点注释,别的什么都没有做,是不是帮助理解这段代码,看看出现频率最高的词是什么,是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,如果是的话,可以释放,不是的话当然不能。

        现在来看看完整的代码:

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. package test.lock;  
  2.   
  3. import java.util.Random;  
  4. import java.util.concurrent.ExecutorService;  
  5. import java.util.concurrent.Executors;  
  6. import java.util.concurrent.ThreadFactory;  
  7.   
  8. public class NaiveLock {  
  9.   
  10.     private static final long NONE = -1;  
  11.     private long owner = NONE;  
  12.   
  13.     private boolean isLooked() {  
  14.         return owner != NONE;  
  15.     }  
  16.   
  17.     public synchronized void lock() {  
  18.         long currentThreadId = Thread.currentThread().getId();  
  19.         if (owner == currentThreadId) {  
  20.             throw new IllegalStateException("Lock has been acquired by current thread");  
  21.         }  
  22.   
  23.         while (this.isLooked()) {  
  24.             System.out.println(String.format("thread %s is waitting lock", currentThreadId));  
  25.             try {  
  26.                 wait();  
  27.             } catch (InterruptedException e) {  
  28.                 e.printStackTrace();  
  29.             }  
  30.         }  
  31.   
  32.         owner = currentThreadId;  
  33.         System.out.println(String.format("Lock is acquired by thread %s", owner));  
  34.     }  
  35.   
  36.     public synchronized void unlock() {  
  37.         if (!this.isLooked() || owner != Thread.currentThread().getId()) {  
  38.             throw new IllegalStateException("Only Lock owner can unlock the lock");  
  39.         }  
  40.   
  41.         System.out.println(String.format("thread %s is unlocking", owner));  
  42.         System.out.println();  
  43.         owner = NONE;  
  44.         notify();  
  45.     }  
  46.   
  47.     public static void main(String[] args) {  
  48.         final NaiveLock lock = new NaiveLock();  
  49.         ExecutorService executor = Executors.newFixedThreadPool(20, new ThreadFactory() {  
  50.   
  51.             private ThreadGroup group = new ThreadGroup("test thread group");  
  52.             {  
  53.                 group.setDaemon(true);  
  54.             }  
  55.   
  56.             @Override  
  57.             public Thread newThread(Runnable r) {  
  58.                 return new Thread(group, r);  
  59.             }  
  60.         });  
  61.   
  62.         for (int i = 0; i < 20; i++) {  
  63.             executor.submit(new Runnable() {  
  64.   
  65.                 @Override  
  66.                 public void run() {  
  67.                     lock.lock();  
  68.                     System.out.println(String.format("thread %s is running...", Thread.currentThread().getId()));  
  69.                     try {  
  70.                         Thread.sleep(new Random().nextInt(1000));  
  71.                     } catch (InterruptedException e) {  
  72.                         e.printStackTrace();  
  73.                     }  
  74.                     lock.unlock();  
  75.                 }  
  76.             });  
  77.         }  
  78.   
  79.     }  
  80.   
  81. }  


运行一下看看结果:

 

 

[plain] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. Lock is acquired by thread 8  
  2. thread 8 is running...  
  3. thread 27 is waitting lock  
  4. thread 26 is waitting lock  
  5. thread 25 is waitting lock  
  6. thread 24 is waitting lock  
  7. thread 23 is waitting lock  
  8. thread 22 is waitting lock  
  9. thread 21 is waitting lock  
  10. thread 20 is waitting lock  
  11. thread 19 is waitting lock  
  12. thread 18 is waitting lock  
  13. thread 17 is waitting lock  
  14. thread 16 is waitting lock  
  15. thread 15 is waitting lock  
  16. thread 14 is waitting lock  
  17. thread 13 is waitting lock  
  18. thread 12 is waitting lock  
  19. thread 11 is waitting lock  
  20. thread 10 is waitting lock  
  21. thread 9 is waitting lock  
  22. thread 8 is unlocking  
  23.   
  24. Lock is acquired by thread 27  
  25. thread 27 is running...  
  26. thread 27 is unlocking  
  27.   
  28. Lock is acquired by thread 26  
  29. thread 26 is running...  
  30. thread 26 is unlocking  
  31.   
  32. Lock is acquired by thread 25  
  33. thread 25 is running...  
  34. thread 25 is unlocking  
  35.   
  36. Lock is acquired by thread 24  
  37. thread 24 is running...  
  38. thread 24 is unlocking  
  39.   
  40. Lock is acquired by thread 23  
  41. thread 23 is running...  
  42. thread 23 is unlocking  
  43.   
  44. Lock is acquired by thread 22  
  45. thread 22 is running...  
  46. thread 22 is unlocking  
  47.   
  48. Lock is acquired by thread 21  
  49. thread 21 is running...  
  50. thread 21 is unlocking  
  51.   
  52. Lock is acquired by thread 20  
  53. thread 20 is running...  
  54. thread 20 is unlocking  
  55.   
  56. Lock is acquired by thread 19  
  57. thread 19 is running...  
  58. thread 19 is unlocking  
  59.   
  60. Lock is acquired by thread 18  
  61. thread 18 is running...  
  62. thread 18 is unlocking  
  63.   
  64. Lock is acquired by thread 17  
  65. thread 17 is running...  
  66. thread 17 is unlocking  
  67.   
  68. Lock is acquired by thread 16  
  69. thread 16 is running...  
  70. thread 16 is unlocking  
  71.   
  72. Lock is acquired by thread 15  
  73. thread 15 is running...  
  74. thread 15 is unlocking  
  75.   
  76. Lock is acquired by thread 14  
  77. thread 14 is running...  
  78. thread 14 is unlocking  
  79.   
  80. Lock is acquired by thread 13  
  81. thread 13 is running...  
  82. thread 13 is unlocking  
  83.   
  84. Lock is acquired by thread 12  
  85. thread 12 is running...  
  86. thread 12 is unlocking  
  87.   
  88. Lock is acquired by thread 11  
  89. thread 11 is running...  
  90. thread 11 is unlocking  
  91.   
  92. Lock is acquired by thread 10  
  93. thread 10 is running...  
  94. thread 10 is unlocking  
  95.   
  96. Lock is acquired by thread 9  
  97. thread 9 is running...  
  98. thread 9 is unlocking  


如果把for循环改成30次,再看一下结果:

 

 

[plain] view plain copy
 
 在CODE上查看代码片派生到我的代码片
    1. Lock is acquired by thread 8  
    2. thread 8 is running...  
    3. thread 27 is waitting lock  
    4. thread 26 is waitting lock  
    5. thread 25 is waitting lock  
    6. thread 24 is waitting lock  
    7. thread 23 is waitting lock  
    8. thread 22 is waitting lock  
    9. thread 21 is waitting lock  
    10. thread 20 is waitting lock  
    11. thread 19 is waitting lock  
    12. thread 18 is waitting lock  
    13. thread 17 is waitting lock  
    14. thread 16 is waitting lock  
    15. thread 15 is waitting lock  
    16. thread 14 is waitting lock  
    17. thread 13 is waitting lock  
    18. thread 12 is waitting lock  
    19. thread 11 is waitting lock  
    20. thread 10 is waitting lock  
    21. thread 9 is waitting lock  
    22. thread 8 is unlocking  
    23.   
    24. Lock is acquired by thread 27  
    25. thread 27 is running...  
    26. thread 8 is waitting lock  
    27. thread 27 is unlocking  
    28.   
    29. Lock is acquired by thread 27  
    30. thread 27 is running...  
    31. thread 26 is waitting lock  
    32. thread 27 is unlocking  
    33.   
    34. Lock is acquired by thread 27  
    35. thread 27 is running...  
    36. thread 25 is waitting lock  
    37. thread 27 is unlocking  
    38.   
    39. Lock is acquired by thread 24  
    40. thread 24 is running...  
    41. thread 27 is waitting lock  
    42. thread 24 is unlocking  
    43.   
    44. Lock is acquired by thread 23  
    45. thread 23 is running...  
    46. thread 24 is waitting lock  
    47. thread 23 is unlocking  
    48.   
    49. Lock is acquired by thread 22  
    50. thread 22 is running...  
    51. thread 23 is waitting lock  
    52. thread 22 is unlocking  
    53.   
    54. Lock is acquired by thread 22  
    55. thread 22 is running...  
    56. thread 21 is waitting lock  
    57. thread 22 is unlocking  
    58.   
    59. Lock is acquired by thread 22  
    60. thread 22 is running...  
    61. thread 20 is waitting lock  
    62. thread 22 is unlocking  
    63.   
    64. Lock is acquired by thread 22  
    65. thread 22 is running...  
    66. thread 19 is waitting lock  
    67. thread 22 is unlocking  
    68.   
    69. Lock is acquired by thread 22  
    70. thread 22 is running...  
    71. thread 18 is waitting lock  
    72. thread 22 is unlocking  
    73.   
    74. Lock is acquired by thread 17  
    75. thread 17 is running...  
    76. thread 17 is unlocking  
    77.   
    78. Lock is acquired by thread 16  
    79. thread 16 is running...  
    80. thread 16 is unlocking  
    81.   
    82. Lock is acquired by thread 15  
    83. thread 15 is running...  
    84. thread 15 is unlocking  
    85.   
    86. Lock is acquired by thread 14  
    87. thread 14 is running...  
    88. thread 14 is unlocking  
    89.   
    90. Lock is acquired by thread 13  
    91. thread 13 is running...  
    92. thread 13 is unlocking  
    93.   
    94. Lock is acquired by thread 12  
    95. thread 12 is running...  
    96. thread 12 is unlocking  
    97.   
    98. Lock is acquired by thread 11  
    99. thread 11 is running...  
    100. thread 11 is unlocking  
    101.   
    102. Lock is acquired by thread 10  
    103. thread 10 is running...  
    104. thread 10 is unlocking  
    105.   
    106. Lock is acquired by thread 9  
    107. thread 9 is running...  
    108. thread 9 is unlocking  
    109.   
    110. Lock is acquired by thread 8  
    111. thread 8 is running...  
    112. thread 8 is unlocking  
    113.   
    114. Lock is acquired by thread 26  
    115. thread 26 is running...  
    116. thread 26 is unlocking  
    117.   
    118. Lock is acquired by thread 25  
    119. thread 25 is running...  
    120. thread 25 is unlocking  
    121.   
    122. Lock is acquired by thread 27  
    123. thread 27 is running...  
    124. thread 27 is unlocking  
    125.   
    126. Lock is acquired by thread 24  
    127. thread 24 is running...  
    128. thread 24 is unlocking  
    129.   
    130. Lock is acquired by thread 23  
    131. thread 23 is running...  
    132. thread 23 is unlocking  
    133.   
    134. Lock is acquired by thread 21  
    135. thread 21 is running...  
    136. thread 21 is unlocking  
    137.   
    138. Lock is acquired by thread 20  
    139. thread 20 is running...  
    140. thread 20 is unlocking  
    141.   
    142. Lock is acquired by thread 19  
    143. thread 19 is running...  
    144. thread 19 is unlocking  
    145.   
    146. Lock is acquired by thread 18  
    147. thread 18 is running...  
    148. thread 18 is unlocking  
posted @ 2016-12-10 10:11  天涯海角路  阅读(114)  评论(0)    收藏  举报