3 回答

TA貢獻1891條經(jīng)驗 獲得超3個贊
無論線程如何,對象是否始終看到其最新的內(nèi)部狀態(tài)?
為了清楚這個問題及其答案的目的,一個物體不做任何事情;它只是記憶。線程是執(zhí)行實體。說一個物體能看到什么東西是誤導性的。它是執(zhí)行對象狀態(tài)的查看/讀取的線程。
這在爪哇語中沒有指定,但是
Executors.newScheduledThreadPool(5);
返回 .ScheduledThreadPoolExecutor
您的代碼正在使用
executorService.scheduleWithFixedDelay(counter, 1, 1, TimeUnit.SECONDS);
調(diào)度線程池資源管理器#scheduleded與固定狀態(tài)
的 javadoc
提交一個周期性操作,該操作在給定的初始延遲之后首先啟用,隨后在一個執(zhí)行終止和下一個執(zhí)行開始之間的給定延遲下啟用。
爪哇類進一步澄清
通過或不重疊計劃的定期任務的連續(xù)執(zhí)行。雖然不同的執(zhí)行可能由不同的線程執(zhí)行,但先前執(zhí)行的效果發(fā)生在后續(xù)執(zhí)行之前。
scheduleAtFixedRate
scheduleWithFixedDelay
因此,保證 每個執(zhí)行 都可以看到 在上一次執(zhí)行遞增后的值。例如,第三次執(zhí)行將讀取一個值,然后再執(zhí)行其增量。Counter#run
count
count
2
對于此特定用例,您不需要或任何其他附加的同步機制。volatile

TA貢獻1804條經(jīng)驗 獲得超8個贊
不,此代碼不是線程安全的,因為在以 開始的不同線程中所做的增量之間沒有任何發(fā)生任何關系。ScheduledExecutorService
要修復此問題,您需要將變量標記為 或切換到 或 。volatile
AtomicInteger
AtomicLong
更新:
@BoristheSpider 如前所述,一般來說,在遞增/遞減的情況下,做一個變量是不夠的,因為遞增/遞減本身不是原子的,并且同時從多個線程調(diào)用它將導致爭用條件和錯過更新。但是,在這種特殊情況下,保證(根據(jù)Javadoc)計劃任務的重疊執(zhí)行,因此即使在增量的情況下,也在此特定情況下也有效。volatile
scheduleWithFixedDelay()
volatile
添加回答
舉報