自学内容网 自学内容网

sychronized锁

sychronized 关键字能成为锁的原因,是因为它提供了**内置锁(Intrinsic Lock)**机制,用于线程同步,确保同一时刻只有一个线程能够访问被标记为 synchronized 的代码块或方法。

原理解析

  1. 内置锁的概念
    每个 Java 对象都关联着一个内置锁,称为 监视器锁(Monitor Lock)。
    • 当一个线程进入 synchronized 方法或代码块时,它必须获得该对象的内置锁。
    • 其他线程在尝试访问同一对象的其他 synchronized 方法或代码块时,必须等待,直到当前线程释放锁。
  2. synchronized 的两种用法
    • 实例方法锁
public synchronized void method() {
    // 线程安全的操作
}

锁住的是当前实例对象 (this),即每个对象有独立的锁。

• 静态方法锁

public static synchronized void staticMethod() {
    // 线程安全的操作
}

锁住的是当前类的 Class 对象,适用于所有线程对类级别资源的同步。

• 代码块锁

public void method() {
    synchronized (this) {
        // 线程安全的操作
    }
}

只锁住代码块,不影响其他非同步代码。

  1. 底层实现
    • synchronized 是 JVM 内置的同步机制。
    • 编译器在字节码中生成了 monitorenter 和 monitorexit 指令,用于获取和释放内置锁。
    • 锁的特性:
    • 重入性:同一个线程可以多次获取它已持有的锁。
    • 可见性:确保变量的内存可见性,即锁释放后,修改的共享变量会对其他线程可见。
  2. 为什么可以成为锁
    • 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)!