Java 中 Synchronized 的基本用法和底层原理

Java 中的 Synchronized 关键字是一种用于实现多线程同步的常用机制。它可以用于修饰方法或代码块,以确保在同一时间只有一个线程可以访问共享资源。在本文中,我们将深入探讨 Synchronized 的底层原理,并提供相应的代码示例。

在这里插入图片描述

一、Synchronized 的基本用法

在 Java 中,Synchronized 可以用于修饰方法或代码块。当 Synchronized 修饰方法时,它将锁定整个方法,使得在同一时间只能有一个线程访问该方法。例如:

public synchronized void foo() {
    // do something
}

当 Synchronized 修饰代码块时,它将锁定该代码块中的对象,使得在同一时间只能有一个线程访问该对象。例如:

public void bar() {
    synchronized (this) {
        // do something
    }
}

在上述示例中,this 表示当前对象,因此 Synchronized 将锁定该对象。

二、Synchronized 的底层原理

Synchronized 的底层原理是基于 Java 中的对象监视器(Monitor)实现的。每个 Java 对象都有一个关联的 Monitor,它是一个内部对象,用于同步访问该对象。当一个线程访问一个被 Synchronized 修饰的方法或代码块时,它会尝试获取该对象的监视器。如果该监视器已被另一个线程占用,则该线程将被阻塞,直到监视器被释放。

在 Java 中,每个对象都有一个与之关联的 Monitor 对象。Monitor 对象包含一个 EntrySet 和 WaitSet,分别用于存储等待锁的线程和等待条件的线程。当一个线程尝试获取一个对象的 Monitor 时,它会先尝试获取 EntrySet 中的锁。如果 EntrySet 中没有锁,那么该线程将获得该对象的 Monitor,并将自己的线程 ID 添加到 EntrySet 中。如果 EntrySet 中已有锁,则该线程将加入 WaitSet 中,并阻塞等待。

当一个线程释放一个对象的 Monitor 时,它将从 EntrySet 中移除自己的线程 ID,并将 WaitSet 中的一个线程移动到 EntrySet 中。如果 WaitSet 中没有线程,则不执行任何操作。这样,EntrySet 中的线程将继续争夺该对象的 Monitor。

三、Synchronized 的代码示例

下面是一个简单的示例,演示了如何使用 Synchronized 实现多线程同步:

public class SynchronizedExample {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public void doWork() {
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 10000; i++) {
                    increment();
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 10000; i++) {
                    increment();
                }
            }
        });

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Count is: " + count);
    }
}

在上述示例中,increment() 方法被声明为 synchronized,这意味着在同一时间只有一个线程可以访问该方法。在 doWork() 方法中,我们创建了两个线程 t1 和 t2,它们都调用 increment() 方法来增加 count 的值。由于 increment() 方法是同步的,因此在同一时间只有一个线程可以访问它,从而确保 count 的值正确地增加。

四、总结

Synchronized 是 Java 中常用的多线程同步机制,它基于对象监视器实现。每个 Java 对象都有一个关联的 Monitor,用于同步访问该对象。当一个线程访问一个被 Synchronized 修饰的方法或代码块时,它会尝试获取该对象的监视器。如果该监视器已被另一个线程占用,则该线程将被阻塞,直到监视器被释放。在实际应用中,我们可以使用 Synchronized 来确保多线程访问共享资源时的正确性和一致性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java老徐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值