
语法

无锁情况
package cn.meowrain;
public class Main {
static int count = 0;
static Object lock = new Object();
public static void main(String[] args) {
getResult();
}
static void getResult() {
Thread thread1 = new Thread(() -> {
for (int i = 1; i <= 10000; i++) {
count++;
}
}, "thread1");
Thread thread2 = new Thread(() -> {
for (int i = 1; i <= 1000; i++) {
count--;
}
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(count);
}
}

有锁情况
package cn.meowrain;
public class Main {
static int count = 0;
static Object lock = new Object();
public static void main(String[] args) {
getResult();
}
static void getResult() {
Thread thread1 = new Thread(() -> {
synchronized (lock) {
for (int i = 1; i <= 10000; i++) {
count++;
}
}
}, "thread1");
Thread thread2 = new Thread(() -> {
synchronized (lock) {
for (int i = 1; i <= 1000; i++) {
count--;
}
}
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(count);
}
}

package cn.meowrain;
public class Main {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(()->{
for (int i = 0;i<100000;i++) {
counter.increment();
}
});
Thread t2 = new Thread(()->{
for(int i = 0;i<10000;i++) {
counter.decrement();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(counter.getCount());
}
}
class Counter {
int count = 0;
public void increment() {
synchronized (this) {
count++;
}
}
public void decrement() {
synchronized (this) {
count--;
}
}
public int getCount() {
synchronized (this) {
return count;
}
}
}
面向对象优化

synchronized

对象上的synchronized
package cn.meowrain;
public class Main {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(()->{
for (int i = 0;i<100000;i++) {
counter.increment();
}
});
Thread t2 = new Thread(()->{
for(int i = 0;i<10000;i++) {
counter.decrement();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(counter.getCount());
}
}
class Counter {
int count = 0;
public void increment() {
synchronized (this) {
count++;
}
}
public void decrement() {
synchronized (this) {
count--;
}
}
public int getCount() {
synchronized (this) {
return count;
}
}
}
加到成员方法上
等价与锁当前对象
加到静态方法上
等价于锁类对象

我的理解很简单,一个是对象锁,一个是类锁
package cn.meowrain;
public class Main {
public static void main(String[] args) {
Counter counterA = new Counter(); // 计数器 A
Counter counterB = new Counter(); // 计数器 B
Counter2.reset(); // 重置静态计数器
// 启动线程操作成员方法锁
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
counterA.increment(); // 操作计数器 A
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
counterB.decrement(); // 操作计数器 B
}
});
// 启动线程操作静态方法锁
Thread thread3 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
Counter2.increment(); // 操作类级计数器
}
});
Thread thread4 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
Counter2.decrement(); // 操作类级计数器
}
});
// 启动线程
thread1.start();
thread2.start();
thread3.start();
thread4.start();
// 等待线程完成
try {
thread1.join();
thread2.join();
thread3.join();
thread4.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 输出结果
System.out.println("Counter A value: " + counterA.getCount()); // 独立的 Counter A
System.out.println("Counter B value: " + counterB.getCount()); // 独立的 Counter B
System.out.println("Counter2 (class-based) value: " + Counter2.getCount()); // 全局静态 Counter2
}
}
// 成员方法锁的计数器
class Counter {
int count = 0;
/**
* 给成员方法加锁,锁定的是每个独立实例
*/
public synchronized void increment() {
count++;
}
public synchronized void decrement() {
count--;
}
public synchronized int getCount() {
return count;
}
}
// 静态方法锁的计数器
class Counter2 {
private static int count = 0;
/**
* 加锁静态方法,锁定的是类对象(全局)
*/
public synchronized static void increment() {
count++;
}
public synchronized static void decrement() {
count--;
}
public synchronized static int getCount() {
return count;
}
public static void reset() {
count = 0;
}
}
用上面这个例子就能说明这个。我们可以看到new 一个Counter,计数器就会重置,也就是每个Counter对象有自己的count,而synchronized加到静态方法上,会让Counter2被全局共享
对象锁(Instance-Level Lock)
代码中对应部分:
在 Counter 类中,你对实例方法(increment、decrement 和 getCount)使用了 synchronized 关键字:
public synchronized void increment() {
count++;
}
- 这里的
synchronized是针对对象实例加锁,锁定的范围是调用该方法的当前实例 (this)。 - 当一个线程调用某个
Counter对象(如counterA)的increment方法时,这个对象会被锁住,其他调用它的线程就必须等待它释放锁资源。但是,不会影响其他实例(如counterB)。
在你的代码中场景:
Thread thread1调用的是counterA.increment(),因此仅锁定counterA对象。Thread thread2调用的是counterB.decrement(),因此仅锁定counterB对象。
因为 counterA 和 counterB 是两个独立对象(实例),线程对不同对象操作时互不干扰。每个对象都有自己独立的锁。
类锁(Class-Level Lock)
代码中对应部分:
在 Counter2 类中,你对静态方法使用了 synchronized 关键字:
public synchronized static void increment() {
count++;
}
- 这里的
synchronized是针对类本身加锁,而不是具体的某个对象。锁定的范围是Counter2.class对象(这个类的字节码对象,是 JVM 中唯一的)。 - 也就是说,无论哪个线程调用
Counter2的increment或decrement方法,只能有一个线程持有该锁资源,其他线程需要等待锁释放。
在你的代码中场景:
Thread thread3调用的是Counter2.increment(),此时会锁定Counter2类对象。Thread thread4调用的是Counter2.decrement(),它需要等到thread3释放Counter2.class的锁。
所有线程在调用 synchronized 静态方法时,都是竞争类级别的锁,无论静态方法是什么。
对象锁与类锁关键区别
| 特性 | 对象锁(成员方法加锁) | 类锁(静态方法加锁) |
|---|---|---|
| 锁范围 | 当前对象实例(this) |
整个类(Class对象) |
| 是否共享 | 不共享,独立 | 共享,所有线程竞争同一个类锁 |
| 场景 | 每个对象独立的线程安全操作 | 全局共享资源的线程安全操作 |
| 你的例子 | Counter 的锁只作用在 counterA 和 counterB 上分别独立运行 |
Counter2 的锁作用在全局共享的静态计数器上 |
为什么用这个例子解释得很清楚?
-
对象锁(Counter 类)
- 由于
counterA和counterB是独立的对象实例,你可以看到这些计数器的值是独立的,互不干扰。 counterA.increment()与counterB.decrement()遵循线程安全,但它们之间没有冲突。
- 由于
-
类锁(Counter2 类)
Counter2中的静态方法,无论多少线程调用,无论它们在哪,都共享一个全局锁。- 多线程对同一个共享计数器操作时,结果是一致和安全的。
输出分析(代码执行后的结果):
counterA.getCount()和counterB.getCount()会显示两个独立的计数值,因为它们是两个独立对象。Counter2.getCount()则可能显示最终的累加结果(由于所有线程竞争的是同一个类锁)。

