掌握聚合最新动态了解行业最新趋势
API接口,开发服务,免费咨询服务

Java中synchronized关键字详解(底层原理、作用、用法)

在多线程编程中,同步是一个至关重要的概念。Java 提供了多种机制来实现线程间的同步,其中 synchronized 关键字是最常用且最基础的工具之一。它能够确保同一时刻只有一个线程访问共享资源,从而避免数据竞争和不一致的问题。本文将深入探讨 synchronized 关键字的底层原理、具体作用以及多种用法,帮助读者全面理解这一核心特性。

一、Synchronized 关键字的基本原理

  1. 同步的概念

定义:同步是指在同一时刻只允许一个线程访问共享资源的操作。

目的:防止多个线程同时修改同一个变量,导致数据不一致或程序崩溃。

  1. Synchronized 的工作机制

锁机制:synchronized 使用对象锁来实现线程同步。

锁的类型:内置锁:每个对象都有一个内置锁(也称为监视器锁)。

可重入锁:支持同一个线程多次获取同一把锁。

示例:

public class Counter {
    private int count = 0;
    public synchronized void increment() {
        count++;
    }
    public synchronized int getCount() {
        return count;
    }
}

解释:

increment() 和 getCount() 方法都被标记为 synchronized,这意味着每次只能有一个线程进入这些方法。

  1. Monitor 锁

Monitor:Java 中的每个对象都有一个与之关联的监视器(Monitor),用于控制线程的访问。

工作流程:当线程调用 synchronized 方法时,它会尝试获取对象的锁。

如果锁已被其他线程持有,则当前线程会被阻塞,直到锁可用。

获取锁后,线程可以执行同步块或方法。

执行完毕后,线程释放锁。

示例:

public class SynchronizedExample {
    private final Object lock = new Object();
    public void methodA() {
        synchronized (lock) {
            // 临界区代码
        }
    }
}

解释:

使用 synchronized 块显式地指定锁对象,确保只有持有 lock 对象的线程才能进入临界区。

二、Synchronized 的具体作用

  1. 保证线程安全

场景:当多个线程访问共享资源时,确保操作的原子性。

示例:

public class SharedResource {
    private int value = 0;
    public synchronized void setValue(int newValue) {
        value = newValue;
    }
    public synchronized int getValue() {
        return value;
    }
}

解释:

setValue() 和 getValue() 方法被同步,确保同一时刻只有一个线程能够修改或读取 value。

  1. 防止死锁

死锁:两个或多个线程互相等待对方释放锁,导致程序无法继续执行。

示例:

public class DeadlockExample {
    private final Object lock1 = new Object();
    private final Object lock2 = new Object();
    public void thread1() {
        synchronized (lock1) {
            System.out.println("Thread 1 holding lock 1...");
            try { Thread.sleep(100); } catch (InterruptedException e) {}
            System.out.println("Thread 1 waiting for lock 2...");
            synchronized (lock2) {
                System.out.println("Thread 1 holding lock 1 & 2...");
            }
        }
    }
    public void thread2() {
        synchronized (lock2) {
            System.out.println("Thread 2 holding lock 2...");
            try { Thread.sleep(100); } catch (InterruptedException e) {}
            System.out.println("Thread 2 waiting for lock 1...");
            synchronized (lock1) {
                System.out.println("Thread 2 holding lock 1 & 2...");
            }
        }
    }
}

解释:

thread1() 和 thread2() 分别获取 lock1 和 lock2,可能导致死锁。

  1. 提高性能

细粒度锁:通过显式指定锁对象,减少不必要的锁范围。

示例:

public class FineGrainedLocking {
    private final Object lock1 = new Object();
    private final Object lock2 = new Object();
    public void operation1() {
        synchronized (lock1) {
            // 临界区代码
        }
    }
    public void operation2() {
        synchronized (lock2) {
            // 临界区代码
        }
    }
}

解释:

将锁范围缩小到最小必要区域,提高并发性能。

三、Synchronized 的多种用法

  1. 方法级别的同步

修饰符:synchronized 可以直接修饰类的方法。

示例:

public class SyncMethodExample {
    public synchronized void methodA() {
        // 临界区代码
    }
    public synchronized void methodB() {
        // 临界区代码
    }
}

解释:

methodA() 和 methodB() 都被同步,同一时刻只有一个线程可以访问它们。

  1. 块级别的同步

语法:

synchronized (object) { ... }

示例:

public class SyncBlockExample {
    private final Object lock = new Object();
    public void method() {
        synchronized (lock) {
            // 临界区代码
        }
    }
}

解释:

显式指定锁对象,提高灵活性。

  1. 静态方法同步

特性:静态方法同步锁的是类本身,而不是实例。

示例:

public class StaticSyncExample {
    public static synchronized void staticMethod() {
        // 临界区代码
    }
}

解释:

staticMethod() 同步锁的是 StaticSyncExample.class。

  1. 同步代码块与锁对象

特点:通过自定义锁对象实现更细粒度的同步。

示例:

public class CustomLockExample {
    private final Object lock = new Object();
    public void method() {
        synchronized (lock) {
            // 临界区代码
        }
    }
}

解释:

使用外部定义的锁对象,而非默认的 this。

四、Synchronized 的优缺点

  1. 优点

简单易用:无需手动管理锁,语法简洁。

自动管理:进入和退出同步块时自动获取和释放锁。

线程安全:确保共享资源的线程安全性。

  1. 缺点

性能问题:锁的获取和释放会带来一定的开销。

死锁风险:不当使用可能导致死锁。

粒度较粗:无法实现更细粒度的锁控制。

Java中synchronized关键字详解(底层原理、作用、用法)

通过本文的学习,我们深入了解了 synchronized 关键字在 Java 中的核心作用及其背后的原理。无论是保证线程安全、防止死锁,还是提高性能,synchronized 都提供了简单而有效的解决方案。然而,在实际应用中,开发者需要注意其潜在的性能瓶颈和死锁风险,合理选择锁的粒度和范围。希望本文的内容能为你的 Java 编程之路提供有力的支持,让你在处理多线程问题时更加得心应手!

声明:所有来源为“聚合数据”的内容信息,未经本网许可,不得转载!如对内容有异议或投诉,请与我们联系。邮箱:marketing@think-land.com

  • 银行卡五元素校验

    验证银行卡、身份证、姓名、手机号是否一致并返回账户类型

    验证银行卡、身份证、姓名、手机号是否一致并返回账户类型

  • 全球天气预报

    支持全球约2.4万个城市地区天气查询,如:天气实况、逐日天气预报、24小时历史天气等

    支持全球约2.4万个城市地区天气查询,如:天气实况、逐日天气预报、24小时历史天气等

  • 购物小票识别

    支持识别各类商场、超市及药店的购物小票,包括店名、单号、总金额、消费时间、明细商品名称、单价、数量、金额等信息,可用于商品售卖信息统计、购物中心用户积分兑换及企业内部报销等场景

    支持识别各类商场、超市及药店的购物小票,包括店名、单号、总金额、消费时间、明细商品名称、单价、数量、金额等信息,可用于商品售卖信息统计、购物中心用户积分兑换及企业内部报销等场景

  • 涉农贷款地址识别

    涉农贷款地址识别,支持对私和对公两种方式。输入地址的行政区划越完整,识别准确度越高。

    涉农贷款地址识别,支持对私和对公两种方式。输入地址的行政区划越完整,识别准确度越高。

  • 人脸四要素

    根据给定的手机号、姓名、身份证、人像图片核验是否一致

    根据给定的手机号、姓名、身份证、人像图片核验是否一致

0512-88869195
数 据 驱 动 未 来
Data Drives The Future