Java多线程锁面试题

原创admin 分类:热门问答 0

Java多线程锁面试题
在Java中,多线程编程是实现程序并发执行的重要方式。为了确保线程安全,锁机制被广泛使用。锁不仅能够保证共享资源在同一时间只能被一个线程访问,还能维护程序的执行顺序,避免出现数据不一致的问题。本文将详细解释Java中的两种常见锁——synchronizedReentrantLock,并通过代码案例展示它们的使用场景。

定义与目的

锁在多线程环境中用于控制对共享资源的访问,以防止多个线程同时修改变量,从而引发数据不一致的问题。锁的目的是保证在任何时刻,只有一个线程可以执行被锁定的代码块或方法。

synchronized与ReentrantLock的区别

synchronized是Java的关键字,而ReentrantLockjava.util.concurrent.locks包中的一个类。以下是它们的主要区别:

特性 synchronized ReentrantLock
用法 作为关键字使用 需要实例化一个锁对象
等待可中断 不支持 支持等待可中断
超时 不支持 支持通过tryLock方法设置超时时间
公平性 不支持选择公平性 可以通过构造函数设置公平性(fairness)
锁绑定条件 不支持 支持通过newCondition创建多个条件对象
可重入性 支持 支持

核心类与方法

  1. synchronized:

    • 作为关键字,可以直接用在方法声明或代码块上。
    • 一个线程在进入synchronized方法或代码块时,自动获取锁,执行完毕后释放锁。
  2. ReentrantLock:

    • ReentrantLock类提供了lock()unlock()方法来获取和释放锁。
    • 它还提供了tryLock()方法,允许在无法获取锁时不阻塞地返回。

使用场景

  • synchronized适合于锁的获取和释放与临界区的进入和退出严格对应,且没有复杂逻辑的场景。
  • ReentrantLock适用于需要更细粒度控制的场景,如尝试非阻塞地获取锁,或在获取锁时设置超时。

代码案例

以下是使用synchronizedReentrantLock的简单示例:

// synchronized的使用
public class SynchronizedExample {
    public static void main(String[] args) {
        SharedObject obj = new SharedObject();
        Thread t1 = new Thread(obj::accessSharedResource);
        Thread t2 = new Thread(obj::accessSharedResource);
        t1.start();
        t2.start();
    }
}

class SharedObject {
    public synchronized void accessSharedResource() {
        System.out.println("Accessing shared resource by " + Thread.currentThread().getName());
    }
}

// ReentrantLock的使用
public class ReentrantLockExample {
    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        Thread t1 = new Thread(() -> {
            lock.lock();
            try {
                accessSharedResource(lock);
            } finally {
                lock.unlock();
            }
        });
        Thread t2 = new Thread(() -> {
            lock.lock();
            try {
                accessSharedResource(lock);
            } finally {
                lock.unlock();
            }
        });
        t1.start();
        t2.start();
    }
}

public static void accessSharedResource(Lock lock) {
    System.out.println("Accessing shared resource by " + Thread.currentThread().getName());
}

总结

在多线程编程中,合理使用锁是保证数据一致性和程序正确性的关键。synchronizedReentrantLock各有适用场景,开发者应根据具体需求选择最合适的锁机制。通过上述代码案例,我们可以看到两种锁在实际编程中的应用,以及它们在控制线程同步方面的重要作用。

猜你喜欢

领取相关Java架构师视频资料

网络安全学习平台视频资料