stampedlock作为java8中出现的新型锁,很可能在大多数场景都可以替代reentrantreadwritelock。它对于读/写都提供了四个接口(换成write为写锁):
readlock()
tryreadlock()
tryreadlock(long time, timeunit unit)
readlockinterruptibly()
这几个方法对应的语义为:
获取读锁(阻塞,不响应中断)
获取读锁(立即)
限时获取读锁(响应中断)
获取读锁(阻塞,响应中断)
然而在readlock方法(即不响应中断)中存在问题(write的版本也是),观察cpu使用率,执行以下代码:
<code>01</code>
<code>public</code> <code>class</code> <code>teststampedlock {</code>
<code>02</code>
<code> </code><code>public</code> <code>static</code> <code>void</code> <code>main(string[] args) </code><code>throws</code> <code>interruptedexception{</code>
<code>03</code>
<code> </code><code>final</code> <code>stampedlock lock = </code><code>new</code> <code>stampedlock();</code>
<code>04</code>
<code> </code><code>new</code> <code>thread(){</code>
<code>05</code>
<code> </code><code>public</code> <code>void</code> <code>run(){</code>
<code>06</code>
<code> </code><code>long</code> <code>readlong = lock.writelock();</code>
<code>07</code>
<code> </code><code>locksupport.parknanos(6100000000l);</code>
<code>08</code>
<code> </code><code>lock.unlockwrite(readlong);</code>
<code>09</code>
<code> </code><code>}</code>
<code>10</code>
<code> </code><code>}.start();</code>
<code>11</code>
<code> </code><code>thread.sleep(</code><code>100</code><code>);</code>
<code>12</code>
<code> </code><code>for</code><code>( </code><code>int</code> <code>i = </code><code>0</code><code>; i < </code><code>3</code><code>; ++i)</code>
<code>13</code>
<code> </code><code>new</code> <code>thread(</code><code>new</code> <code>occupiedcpureadthread(lock)).start();</code>
<code>14</code>
<code> </code><code>}</code>
<code>15</code>
<code> </code><code>private</code> <code>static</code> <code>class</code> <code>occupiedcpureadthread </code><code>implements</code> <code>runnable{</code>
<code>16</code>
<code> </code><code>private</code> <code>stampedlock lock;</code>
<code>17</code>
<code> </code><code>public</code> <code>occupiedcpureadthread(stampedlock lock){</code>
<code>18</code>
<code> </code><code>this</code><code>.lock = lock;</code>
<code>19</code>
<code> </code><code>}</code>
<code>20</code>
<code> </code><code>public</code> <code>void</code> <code>run(){</code>
<code>21</code>
<code> </code><code>thread.currentthread().interrupt();</code>
<code>22</code>
<code> </code><code>long</code> <code>lockr = lock.readlock();</code>
<code>23</code>
<code> </code><code>system.out.println(thread.currentthread().getname() + </code><code>" get read lock"</code><code>);</code>
<code>24</code>
<code> </code><code>lock.unlockread(lockr);</code>
<code>25</code>
<code>26</code>
<code>27</code>
<code>}</code>
先开启一个线程获取写锁并保持6秒,再开启三个带着中断状态的线程去获取读锁(readlock方法),结果是3个核心被占据了近6秒。
原因在于没有使用保存/复原中断状态的机制,通过hack源码,插入保存中断和返回前恢复中断的相关代码即可修复:
<code>1</code>
<code>boolean</code> <code>interrupted = </code><code>false</code><code>;</code>
<code>if</code><code>(interrupted)</code>
<code>2</code>
<code> </code><code>thread.currentthread().interrupt();</code>
<code>3</code>
<code>return</code> <code>ns;</code>
<code>if</code><code>(thread.interrupted()){</code>
<code> </code><code>if</code><code>(interruptible)</code>
<code> </code><code>return</code> <code>cancelwaiter(node, p, </code><code>true</code><code>);</code>
<code>4</code>
<code> </code><code>else</code>
<code>5</code>
<code> </code><code>interrupted = </code><code>true</code><code>;</code>
<code>6</code>
<a href="https://github.com/zuai/hui">stampedlock</a>