sychronized锁
sychronized 关键字能成为锁的原因,是因为它提供了**内置锁(Intrinsic Lock)**机制,用于线程同步,确保同一时刻只有一个线程能够访问被标记为 synchronized 的代码块或方法。
原理解析
- 内置锁的概念
每个 Java 对象都关联着一个内置锁,称为 监视器锁(Monitor Lock)。
• 当一个线程进入 synchronized 方法或代码块时,它必须获得该对象的内置锁。
• 其他线程在尝试访问同一对象的其他 synchronized 方法或代码块时,必须等待,直到当前线程释放锁。 - synchronized 的两种用法
• 实例方法锁
public synchronized void method() {
// 线程安全的操作
}
锁住的是当前实例对象 (this),即每个对象有独立的锁。
• 静态方法锁
public static synchronized void staticMethod() {
// 线程安全的操作
}
锁住的是当前类的 Class 对象,适用于所有线程对类级别资源的同步。
• 代码块锁
public void method() {
synchronized (this) {
// 线程安全的操作
}
}
只锁住代码块,不影响其他非同步代码。
- 底层实现
• synchronized 是 JVM 内置的同步机制。
• 编译器在字节码中生成了 monitorenter 和 monitorexit 指令,用于获取和释放内置锁。
• 锁的特性:
• 重入性:同一个线程可以多次获取它已持有的锁。
• 可见性:确保变量的内存可见性,即锁释放后,修改的共享变量会对其他线程可见。 - 为什么可以成为锁
• synchronized 借助于 Java 对象的监视器锁机制,天然支持线程排他性和共享资源的安全访问。
• 配合 JVM 的内存模型,保证了变量的可见性和操作的有序性。
举例说明
以下代码展示了 synchronized 如何控制线程同步:
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter.getCount()); // 输出 2000
}
}
在这个例子中,synchronized 确保了多个线程对 increment 方法的访问是互斥的,避免了数据竞争。
原文地址:https://blog.csdn.net/qq_34358193/article/details/143805394
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!