亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

關于Java中擴展線程安全類的問題

關于Java中擴展線程安全類的問題

青春有我 2018-10-04 08:10:48
最近在讀《Java并發編程實戰》,里面的4.4.1節,有個例子:假設我們需要一個線程安全的List,它需要提供給我們一個原子的“缺少即加入(put-if-absent)”操作。并提供了2種實現:非線程安全的“缺少即加入”實現public class ListHelper<E> {     public List<E> list = Collections.synchronizedList(new ArrayList<E>());        public synchronized boolean putIfAbsent(E x) {            boolean absent = !list.contains(x);                 if (absent) {                         list.add(x);         }                 return absent;     } }使用客戶端加鎖實現的“缺少即加入”public class ListHelper<E> {     public List<E> list = Collections.synchronizedList(new ArrayList<E>());         public boolean putIfAbsent(E x) {         synchronized (list) {                     boolean absent = !list.contains(x);                           if (absent) {                                      list.add(x);             }                    return absent;         }     } }感覺書中的翻譯比較晦澀,一直沒理解這里為什么第一個是非線程安全的而第二個就是線程安全的,請大神看看是怎么回事
查看完整描述

2 回答

?
蕪湖不蕪

TA貢獻1796條經驗 獲得超7個贊

首先要明白,synchronize加鎖的一般都是對某個對象而言的(也可以對類進行加鎖)。
1中非線程安全的synchronized的加鎖對象其實是ListHelper<E>實例化的對象,而不是list,其他的線程無法再對該ListHelper<E>實例化的對象進行操作,對于該例,就是無法再進行putIfAbsent()方法的使用,但是其中的list是public的,所以可以直接對list進行操作,比如list.add()等操作,進而造成線程不安全

查看完整回答
反對 回復 2018-10-14
?
慕尼黑的夜晚無繁華

TA貢獻1864條經驗 獲得超6個贊

大概是由于public List<E> list = Collections.synchronizedList(new ArrayList<E>());的這個list是public的,可以被直接修改的。
假如有多個線程直接修改這個list。
方法1雖然把putIfAbsent(E x)這個方法加鎖了,但是其他線程依然可以修改由于public暴露出來的list。
比如線程A:listHelper.list.add(x)的時候,線程B剛好在執行boolean absent = !list.contains(x);,有可能線程A把x添加進去了,但是線程B的absent也判斷為true,然后線程B就再次add了x。
方法2是根據list加鎖,所以只有持有list的鎖才能進入判斷和添加,當線程A在listHelper.list.add(x)的時候,線程B是不能進入到synchronized (list)方法內的

查看完整回答
反對 回復 2018-10-14
  • 2 回答
  • 0 關注
  • 833 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號