天天看點

Oracle官方并發教程之一個同步類的例子

<code>01</code>

<code>public</code> <code>class</code> <code>synchronizedrgb {</code>

<code>02</code>

<code>03</code>

<code>    </code><code>// values must be between 0 and 255.</code>

<code>04</code>

<code>    </code><code>private</code> <code>int</code> <code>red;</code>

<code>05</code>

<code>    </code><code>private</code> <code>int</code> <code>green;</code>

<code>06</code>

<code>    </code><code>private</code> <code>int</code> <code>blue;</code>

<code>07</code>

<code>    </code><code>private</code> <code>string name;</code>

<code>08</code>

<code>09</code>

<code>    </code><code>private</code> <code>void</code> <code>check(</code><code>int</code> <code>red,</code>

<code>10</code>

<code>                       </code><code>int</code> <code>green,</code>

<code>11</code>

<code>                       </code><code>int</code> <code>blue) {</code>

<code>12</code>

<code>        </code><code>if</code> <code>(red &lt; </code><code>0</code> <code>|| red &gt; </code><code>255</code>

<code>13</code>

<code>            </code><code>|| green &lt; </code><code>0</code> <code>|| green &gt; </code><code>255</code>

<code>14</code>

<code>            </code><code>|| blue &lt; </code><code>0</code> <code>|| blue &gt; </code><code>255</code><code>) {</code>

<code>15</code>

<code>            </code><code>throw</code> <code>new</code> <code>illegalargumentexception();</code>

<code>16</code>

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

<code>17</code>

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

<code>18</code>

<code>19</code>

<code>    </code><code>public</code> <code>synchronizedrgb(</code><code>int</code> <code>red,</code>

<code>20</code>

<code>                           </code><code>int</code> <code>green,</code>

<code>21</code>

<code>                           </code><code>int</code> <code>blue,</code>

<code>22</code>

<code>                           </code><code>string name) {</code>

<code>23</code>

<code>        </code><code>check(red, green, blue);</code>

<code>24</code>

<code>        </code><code>this</code><code>.red = red;</code>

<code>25</code>

<code>        </code><code>this</code><code>.green = green;</code>

<code>26</code>

<code>        </code><code>this</code><code>.blue = blue;</code>

<code>27</code>

<code>        </code><code>this</code><code>.name = name;</code>

<code>28</code>

<code>29</code>

<code>30</code>

<code>    </code><code>public</code> <code>void</code> <code>set(</code><code>int</code> <code>red,</code>

<code>31</code>

<code>                    </code><code>int</code> <code>green,</code>

<code>32</code>

<code>                    </code><code>int</code> <code>blue,</code>

<code>33</code>

<code>                    </code><code>string name) {</code>

<code>34</code>

<code>35</code>

<code>        </code><code>synchronized</code> <code>(</code><code>this</code><code>) {</code>

<code>36</code>

<code>            </code><code>this</code><code>.red = red;</code>

<code>37</code>

<code>            </code><code>this</code><code>.green = green;</code>

<code>38</code>

<code>            </code><code>this</code><code>.blue = blue;</code>

<code>39</code>

<code>            </code><code>this</code><code>.name = name;</code>

<code>40</code>

<code>41</code>

<code>42</code>

<code>43</code>

<code>    </code><code>public</code> <code>synchronized</code> <code>int</code> <code>getrgb() {</code>

<code>44</code>

<code>        </code><code>return</code> <code>((red &lt;&lt; </code><code>16</code><code>) | (green &lt;&lt; </code><code>8</code><code>) | blue);</code>

<code>45</code>

<code>46</code>

<code>47</code>

<code>    </code><code>public</code> <code>synchronized</code> <code>string getname() {</code>

<code>48</code>

<code>        </code><code>return</code> <code>name;</code>

<code>49</code>

<code>50</code>

<code>51</code>

<code>    </code><code>public</code> <code>synchronized</code> <code>void</code> <code>invert() {</code>

<code>52</code>

<code>        </code><code>red = </code><code>255</code> <code>- red;</code>

<code>53</code>

<code>        </code><code>green = </code><code>255</code> <code>- green;</code>

<code>54</code>

<code>        </code><code>blue = </code><code>255</code> <code>- blue;</code>

<code>55</code>

<code>        </code><code>name = </code><code>"inverse of "</code> <code>+ name;</code>

<code>56</code>

<code>57</code>

<code>}</code>

使用synchronizedrgb時需要小心,避免其處于不一緻的狀态。例如一個線程執行了以下代碼:

<code>1</code>

<code>synchronizedrgb color =</code>

<code>2</code>

<code>    </code><code>new</code> <code>synchronizedrgb(</code><code>0</code><code>, </code><code>0</code><code>, </code><code>0</code><code>, </code><code>"pitch black"</code><code>);</code>

<code>3</code>

<code>...</code>

<code>4</code>

<code>int</code> <code>mycolorint = color.getrgb();      </code><code>//statement 1</code>

<code>5</code>

<code>string mycolorname = color.getname(); </code><code>//statement 2</code>

如果有另外一個線程在statement 1之後、statement 2之前調用了color.set方法,那麼mycolorint的值和mycolorname的值就會不比對。為了避免出現這樣的結果,必須要像下面這樣把這兩條語句綁定到一塊執行:

<code>synchronized</code> <code>(color) {</code>

<code>    </code><code>int</code> <code>mycolorint = color.getrgb();</code>

<code>    </code><code>string mycolorname = color.getname();</code>

這種不一緻的問題隻可能發生在可變對象上。