MST

星途 面试题库

面试题:Java Web应用中如何使用synchronized关键字实现并发控制

在Java Web应用场景下,假设有一个多线程访问的共享资源,例如一个账户余额,需要对其进行加减操作。请描述如何使用synchronized关键字来确保线程安全,同时说明synchronized关键字修饰静态方法和实例方法时在并发控制上有什么不同。
49.4万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

使用 synchronized 关键字确保线程安全实现账户余额加减操作

  1. 定义账户类
public class Account {
    private double balance;

    public Account(double initialBalance) {
        this.balance = initialBalance;
    }

    // 使用synchronized修饰实例方法实现对账户余额的加减操作
    public synchronized void deposit(double amount) {
        balance += amount;
    }

    public synchronized void withdraw(double amount) {
        if (balance >= amount) {
            balance -= amount;
        }
    }

    public double getBalance() {
        return balance;
    }
}
  1. 解释
    • 当多个线程调用 depositwithdraw 方法时,由于这些方法被 synchronized 修饰,同一时刻只有一个线程能够进入这些方法执行操作。
    • 这就确保了对 balance 这个共享资源的操作是线程安全的,避免了多个线程同时修改 balance 导致数据不一致的问题。

synchronized 修饰静态方法和实例方法在并发控制上的不同

  1. synchronized 修饰实例方法
    • 锁对象:锁的是当前类的实例对象 this
    • 并发控制:多个线程访问同一个实例对象的 synchronized 实例方法时,会竞争同一个锁,同一时刻只有一个线程能执行该实例方法。但是,如果多个线程访问不同实例对象的 synchronized 实例方法,由于锁对象不同(每个实例对象都有自己的锁),它们不会互相竞争锁,可以并发执行。
    • 示例
public class SynchronizedInstanceMethodExample {
    public synchronized void instanceMethod() {
        // 方法体
    }
}

假设有两个 SynchronizedInstanceMethodExample 的实例 obj1obj2,线程 thread1 调用 obj1.instanceMethod(),线程 thread2 调用 obj2.instanceMethod(),这两个线程可以同时执行,因为它们锁的是不同的实例对象。

  1. synchronized 修饰静态方法
    • 锁对象:锁的是当前类的 Class 对象(因为静态方法属于类,不属于某个实例)。
    • 并发控制:无论有多少个实例对象,只要是调用该类的 synchronized 静态方法,所有线程都会竞争同一个 Class 对象的锁。也就是说,同一时刻只有一个线程能执行该类的任何 synchronized 静态方法。
    • 示例
public class SynchronizedStaticMethodExample {
    public static synchronized void staticMethod() {
        // 方法体
    }
}

假设有两个 SynchronizedStaticMethodExample 的实例 obj1obj2,线程 thread1 通过 obj1.staticMethod() 调用静态方法,线程 thread2 通过 obj2.staticMethod() 调用静态方法,这两个线程不能同时执行,因为它们竞争的是同一个 SynchronizedStaticMethodExample.class 锁。