Java中使用synchronized方法递增int变量时,是否必须声明为volatile?
使用synchronized方法时,是否还需要用volatile修饰变量?
结论很明确:不需要,仅用synchronized方法就足够保证多线程环境下递增操作的线程安全,以及变量的可见性。
核心原因:
synchronized本身具备完整的内存语义:线程进入synchronized方法/代码块时,会强制从主内存读取变量最新值到自身工作内存;退出同步区域时,会将工作内存中修改后的变量值写回主内存,同时让其他线程工作内存中该变量的缓存失效,确保后续读取的都是最新值。- 你代码里的
increment()方法是synchronized的,counter++这个包含「读取-修改-写入」的三步操作会被完整加锁保护,既避免了多线程下的原子性问题,也通过synchronized的内存语义保证了counter变量的可见性。
代码相关补充说明:
你的Counter类中,getCounter()方法未加synchronized,如果该方法会被多个线程并发调用,可能读取到旧的counter值——但这和是否给counter加volatile无关,解决方式要么给getCounter()也加上synchronized,要么确保只有当所有increment操作完成后才调用getCounter()(就像你测试代码里等待线程池终止后再读取的逻辑),这种场景下也不会有问题。
至于你看到讲师同时使用synchronized方法和volatile变量,这属于冗余写法,实际场景中完全没必要——synchronized已经覆盖了volatile能提供的可见性保障,还额外提供了原子性保障。
你的代码示例:
ClientTest 类
public class ClientTest { public static void main(String[] args) { ExecutorService executorService = null; Counter counter = new Counter(); try { executorService = Executors.newFixedThreadPool(2); Runnable task1 = () -> { for (int i = 1; i <= 20000; i++) { counter.increment(); } }; Runnable task2 = () -> { for (int i = 1; i <= 80000; i++) { counter.increment(); } }; executorService.submit(task1); executorService.submit(task2); executorService.awaitTermination(1, TimeUnit.SECONDS); System.out.println("Final counter value: " + counter.getCounter()); } catch (InterruptedException e) { throw new RuntimeException(e); } } }
Counter 类
public class Counter { private int counter; public int getCounter() { return counter; } public synchronized void increment() { counter++; } }
内容的提问来源于stack exchange,提问作者elvis
相关产品推荐
相关产品推荐

