天天看点

CopyOnWriteArrayList类set方法疑惑?

在淘宝内网有位同事提了一个很好的问题,大家能否帮忙解答下?

在CopyOnWriteArrayList类的set方法中有一段setArray(elements)代码,实际上这段代码并未对elements做任何改动,实现的volatile语意并不对CopyOnWriteArrayList实例产生任何影响,为什么还是要保留这行语句?见以下代码红体部分:

<a href="http://ifeve.com/copyonwritearraylist-set/#viewSource">查看源代码</a>

<code>01</code>

<code>/** The array, accessed only via getArray/setArray. */</code>

<code>02</code>

<code>private</code> <code>volatile</code> <code>transient</code> <code>Object[] array;</code>

<code>03</code>

<code>04</code>

<code>/**</code>

<code>05</code>

<code> </code><code>* Replaces the element at the specified position in this list with the</code>

<code>06</code>

<code> </code><code>* specified element.</code>

<code>07</code>

<code> </code><code>*</code>

<code>08</code>

<code> </code><code>* @throws IndexOutOfBoundsException {@inheritDoc}</code>

<code>09</code>

<code> </code><code>*/</code>

<code>10</code>

<code>public</code> <code>E set(</code><code>int</code> <code>index, E element) {</code>

<code>11</code>

<code>    </code><code>final</code> <code>ReentrantLock lock =</code><code>this</code><code>.lock;</code>

<code>12</code>

<code>    </code><code>lock.lock();</code>

<code>13</code>

<code>    </code><code>try</code> <code>{</code>

<code>14</code>

<code>        </code><code>Object[] elements = getArray();</code>

<code>15</code>

<code>        </code><code>E oldValue = get(elements, index);</code>

<code>16</code>

<code>17</code>

<code>        </code><code>if</code> <code>(oldValue != element) {</code>

<code>18</code>

<code>            </code><code>int</code> <code>len = elements.length;</code>

<code>19</code>

<code>            </code><code>Object[] newElements = Arrays.copyOf(elements, len);</code>

<code>20</code>

<code>            </code><code>newElements[index] = element;</code>

<code>21</code>

<code>            </code><code>setArray(newElements);</code>

<code>22</code>

<code>        </code><code>}</code><code>else</code> <code>{</code>

<code>23</code>

<code>            </code><code>// Not quite a no-op; ensures volatile write semantics</code>

<code>24</code>

<code>            </code><code>setArray(elements);</code>

<code>25</code>

<code>        </code><code>}</code>

<code>26</code>

<code>        </code><code>return</code> <code>oldValue;</code>

<code>27</code>

<code>    </code><code>}</code><code>finally</code> <code>{</code>

<code>28</code>

<code>        </code><code>lock.unlock();</code>

<code>29</code>

<code>    </code><code>}</code>

<code>30</code>

<code>}</code>

<code>31</code>

<code>32</code>

<code>33</code>

<code> </code><code>* Sets the array.</code>

<code>34</code>

<code>35</code>

<code>final</code> <code>void</code> <code>setArray(Object[] a) {</code>

<code>36</code>

<code>    </code><code>array = a;</code>

<code>37</code>

<code>38</code>

<code>39</code>

<code>40</code>

<code> </code><code>* Gets the array.  Non-private so as to also be accessible</code>

<code>41</code>

<code> </code><code>* from CopyOnWriteArraySet class.</code>

<code>42</code>

<code>43</code>

<code>final</code> <code>Object[] getArray() {</code>

<code>44</code>

<code>    </code><code>return</code> <code>array;</code>

<code>45</code>

这个问题在concurrency-interest邮件列表里也有人讨论:

<a href="http://cs.oswego.edu/pipermail/concurrency-interest/2010-February/006886.html">http://cs.oswego.edu/pipermail/concurrency-interest/2010-February/006886.html</a>