由于并發問題,局部變量成為最終變量或有效最終變量的原因。在 jls 8 規范中,有以下規定。對有效最終變量的限制禁止訪問動態更改的局部變量,捕獲這些變量可能會引入并發問題。一切都很好,很甜蜜,但我做了一個小實驗。如果我同步該方法,這將消除動態更改局部變量的可能性,因為我保證只有一個線程可以執行此代碼。但編譯拋出了一個錯誤,指出它必須是最終的或有效的最終的。邏輯對嗎?考慮以下代碼: public synchronized void capture() { int localVariable = 100; Interf i = (text) -> System.out.println(text + localVariable); i.m1("This local variable is: "); localVariable = 1000; }}
3 回答

阿晨1998
TA貢獻2037條經驗 獲得超6個贊
答案很簡單,您的變量在方法結束時超出了范圍。使用有效的最終變量可以輕松解決這個問題,因為編譯器只是將值復制到 lambda 中。由于 lambda 表達式中的代碼也可以在方法外部運行(其中可修改變量已被垃圾收集),因此這是行不通的。您也不能指望編譯器以某種方式復制您的變量,然后在 lambda 表達式之外修改它時動態更改它。我希望這能解決問題。

慕村225694
TA貢獻1880條經驗 獲得超4個贊
想象一下您創建的 CompletableFuture 由 ForkJoinPool 或其他執行器執行的 lambda?
這就是為什么此方法上的同步不足以推翻局部變量有效為最終的規則。lambda 將同步執行并同步,但它創建的異步任務不會。

婷婷同學_
TA貢獻1844條經驗 獲得超8個贊
但編譯拋出了一個錯誤,指出它必須是最終的或有效的最終的。
那是因為它是按照規則進行的。不,是,沒有但是;您是否真正防范了所有并發問題并不重要 - 如果它不是有效的最終版本,它就不會編譯。
在您這里的簡單示例中,可能沒問題。然而,使方法同步是無關緊要的,因為無論如何局部變量總是與它們的每線程調用相關聯。編譯器擔心的是方法本身上下文中的線程問題,并且在使用 lambda 時很容易發生這種情況(在非最終變量的狀態可能發生變化之后,可能會在將來的任意時間執行) ,如果有的話,根本不清楚應該使用什么狀態 - 初始狀態還是更新后的狀態。)
添加回答
舉報
0/150
提交
取消