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
相关产品推荐
相关产品推荐

