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

Java多线程程序中锁无法作用于共享变量的原因排查

Java并发锁失效原因及修正方案

你的锁之所以无法生效,核心问题是所有线程没有共用同一把锁,下面逐个分析你代码里的错误点:

  • 循环内创建局部锁对象:Object lock1 = new Object();写在while循环内部,每次循环都会生成全新的对象。synchronized锁的是这个局部对象,每个线程甚至每次循环都在用不同的锁,完全无法同步对static counter的修改。
  • 实例级锁无法同步静态变量:不管是成员变量lock1、lock2还是ReentrantLock lock,只要是非static修饰的,每个Concurrent线程实例都会持有自己的锁对象,线程之间的锁互不干扰,自然锁不住共享的static counter。
  • synchronized修饰run方法的误区:synchronized修饰实例方法时,锁的是当前线程对象(this),每个线程实例的this都是独立的,同样无法实现多线程对静态变量的同步。

正确实现方式一:使用static共享锁对象

import java.util.concurrent.locks.*;

public class Concurrent extends Thread {
    // 用static修饰,让所有线程共享同一把锁
    private static final Object lock = new Object();
    static long counter = 0;
    static long threads = 10;
    static long count_each = 1000000;

    @Override
    public void run() {
        long count = count_each;
        while (count-- > 0) {
            // 所有线程竞争同一把lock对象
            synchronized (lock) {
                counter++;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread[] threadArr = new Thread[(int) threads];
        for (int i = 0; i < threads; i++) {
            threadArr[i] = new Concurrent();
            threadArr[i].start();
        }
        // 等待所有线程执行完毕
        for (Thread t : threadArr) {
            t.join();
        }
        // 预期输出10*1000000=10000000
        System.out.println("Counter: " + counter);
    }
}

正确实现方式二:使用static的ReentrantLock

import java.util.concurrent.locks.*;

public class Concurrent extends Thread {
    // static锁,确保所有线程共用同一把锁
    private static final ReentrantLock lock = new ReentrantLock();
    static long counter = 0;
    static long threads = 10;
    static long count_each = 1000000;

    @Override
    public void run() {
        long count = count_each;
        while (count-- > 0) {
            lock.lock();
            try {
                counter++;
            } finally {
                // 必须在finally中释放锁,避免异常导致锁无法释放
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread[] threadArr = new Thread[(int) threads];
        for (int i = 0; i < threads; i++) {
            threadArr[i] = new Concurrent();
            threadArr[i].start();
        }
        for (Thread t : threadArr) {
            t.join();
        }
        System.out.println("Counter: " + counter);
    }
}

关键注意点

  • 同步锁的核心是多线程必须竞争同一把锁,所以锁对象必须是所有线程可见的共享对象(通常用static修饰)。
  • 使用ReentrantLock时,一定要在finally块中释放锁,防止线程抛出异常后锁一直被占用,引发死锁。
  • 对静态变量的同步操作,优先使用静态锁,避免用实例锁做无效同步。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 00:20:44