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>