You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

synchronized块锁失效原因:多线程自增结果不符预期

为什么synchronized块用Integer做锁无法保证线程安全?

你的代码中两个线程各自对cnt执行10万次自增操作,预期结果应为200000,但实际输出偏小,核心问题出在锁对象本身被动态改变,导致同步机制失效:

问题根源

  • Integer是不可变类,cnt++并非直接修改原对象的值,而是执行了cnt = Integer.valueOf(cnt.intValue() + 1)——每次自增都会创建一个新的Integer对象,并让cnt指向这个新对象。
  • synchronized块锁的是当前cnt指向的对象实例,每次自增后cnt指向的对象发生变化,两个线程可能各自持有不同对象的锁,完全起不到互斥作用,最终出现多个线程同时修改值的线程安全问题,导致计数丢失。

解决方案

针对这个问题,有几种可靠的修复方式:

1. 使用固定不变的锁对象

在SharedObject类中定义一个固定的锁对象,确保所有线程都锁定同一个实例:

public class Main {
    public static void main(String[] args) throws InterruptedException {
        SharedObject sharedObject = new SharedObject();
        Thread producer = new Thread(sharedObject::produce);
        Thread consumer = new Thread(sharedObject::consume);
        producer.start();
        consumer.start();
        producer.join();
        consumer.join();
        System.out.println(sharedObject.cnt);
    }
    static class SharedObject {
        int cnt = 0;
        // 固定锁对象,始终指向同一个实例
        private final Object lock = new Object();
        
        void produce() {
            for(int i=0; i<100000; i++) {
                synchronized (lock) {
                    cnt++;
                }
            }
        }
        void consume() {
            for(int i=0; i<100000; i++) {
                synchronized (lock) {
                    cnt++;
                }
            }
        }
    }
}

2. 使用AtomicInteger原子类

利用Java并发包提供的原子类,无需手动加锁即可实现线程安全的自增操作:

import java.util.concurrent.atomic.AtomicInteger;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        SharedObject sharedObject = new SharedObject();
        Thread producer = new Thread(sharedObject::produce);
        Thread consumer = new Thread(sharedObject::consume);
        producer.start();
        consumer.start();
        producer.join();
        consumer.join();
        System.out.println(sharedObject.cnt.get());
    }
    static class SharedObject {
        AtomicInteger cnt = new AtomicInteger(0);
        
        void produce() {
            for(int i=0; i<100000; i++) {
                cnt.incrementAndGet();
            }
        }
        void consume() {
            for(int i=0; i<100000; i++) {
                cnt.incrementAndGet();
            }
        }
    }
}

3. 锁定当前对象或使用synchronized方法

如果不需要单独的锁对象,也可以直接锁定this(当前SharedObject实例),或者把方法声明为synchronized:

public class Main {
    public static void main(String[] args) throws InterruptedException {
        SharedObject sharedObject = new SharedObject();
        Thread producer = new Thread(sharedObject::produce);
        Thread consumer = new Thread(sharedObject::consume);
        producer.start();
        consumer.start();
        producer.join();
        consumer.join();
        System.out.println(sharedObject.cnt);
    }
    static class SharedObject {
        int cnt = 0;
        
        // 使用synchronized方法,锁对象为当前实例this
        synchronized void produce() {
            for(int i=0; i<100000; i++) {
                cnt++;
            }
        }
        synchronized void consume() {
            for(int i=0; i<100000; i++) {
                cnt++;
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者madina11906036

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 04:35:17