Java面试记录

文章目录

  • 1、final关键字
  • 2、synchronized关键字
    • (1)synchronized的功能:
    • (2)synchronized的底层实现原理:
  • 3、Java中线程同步的实现方法
    • (1). 使用synchronized关键字:
    • (2). 使用Lock接口:
    • (3). 使用volatile关键字:
    • (4). 使用wait()和notify()/notifyAll()方法:
  • 4、ReentrantLock
    • 概念:
    • 功能:
    • 实现:
    • 原理:
    • 与synchronized的异同:
  • 5、volatile关键字
    • 概念:
    • 功能:
    • 实现原理:
    • 与synchronized的异同:

1、final关键字

它可以用来修饰类、方法和变量。

  1. 修饰类:

    • 当一个类被final修饰时,它表示该类不能被继承,即它是最终的类,不能有子类。
  2. 修饰方法:

    • 当一个方法被final修饰时,它表示该方法不能被子类重写,即它是最终的方法,子类无法修改它的实现。
  3. 修饰变量:

    • 当一个变量被final修饰时,它表示该变量的值不能被修改,即它是一个常量。被final修饰的变量必须在声明时进行初始化,并且不能再次赋值。
      在Java中,synchronized是一个关键字,它用于实现多线程的同步。它可以用来修饰方法或代码块,在多线程环境下确保共享资源的安全访问。

2、synchronized关键字

它可以用来修饰类、方法和变量。

(1)synchronized的功能:

  1. 保证线程安全:synchronized关键字可以保证在同一时间只有一个线程可以执行被synchronized修饰的方法或代码块,从而避免多线程同时对共享资源进行修改而产生的数据不一致问题。

(2)synchronized的底层实现原理:

在Java中,synchronized关键字的底层实现主要依赖于对象的监视器锁(也称为内置锁或管程)。

  1. 对象的监视器锁:每个对象都有一个与之关联的监视器锁,当一个线程访问一个synchronized方法或代码块时,它会自动获得该对象的监视器锁;其他线程必须等待该线程释放锁后才能访问。

  2. 互斥性:synchronized保证了同一时间只有一个线程可以获得对象的监视器锁,其他线程必须等待,实现了互斥性,避免了多线程同时访问共享资源的问题。

  3. 可重入性:同一个线程可以多次获得同一个对象的监视器锁,synchronized关键字对重入锁提供了支持,避免了死锁的发生。

需要注意的是,synchronized关键字只能保证同一个对象的同步,不同对象之间的同步需要其他机制(例如使用Lock接口)来实现。此外,synchronized关键字的使用会带来性能的一定损耗,因此在设计多线程应用程序时,需要合理使用synchronized来保证线程安全,同时尽量避免不必要的同步。

3、Java中线程同步的实现方法

有以下几种:

(1). 使用synchronized关键字:

synchronized关键字可以修饰方法或代码块,保证同一时间只有一个线程可以执行被synchronized修饰的方法或代码块。这样可以确保共享资源的安全访问。

(2). 使用Lock接口:

Java提供了Lock接口及其实现类,如ReentrantLock,可以手动控制线程的同步。使用Lock接口可以实现更灵活的线程同步,可以实现公平锁和非公平锁,并提供了更多的功能,如可重入性、条件变量等。

(3). 使用volatile关键字:

volatile关键字可以保证被修饰的变量在多线程环境下的可见性,即一个线程对volatile变量的修改对其他线程是可见的。但是volatile不能保证原子性,无法解决复合操作的线程安全问题。

(4). 使用wait()和notify()/notifyAll()方法:

这两个方法是Object类中的方法,用于实现线程之间的协作。wait()方法使当前线程等待,直到其他线程调用notify()或notifyAll()方法唤醒它;notify()方法唤醒一个等待的线程;notifyAll()方法唤醒所有等待的线程。

以上方法都可以实现线程同步,但根据具体的需求和场景选择合适的方法。

4、ReentrantLock

是Java.util.concurrent包中的一个实现了Lock接口的类,它提供了一种可重入的互斥锁。下面对ReentrantLock进行详细介绍:

概念:

ReentrantLock是一个可重入的互斥锁,它允许线程重复获取同一个锁。与synchronized相比,ReentrantLock提供了更多的灵活性和功能。

功能:

  1. 互斥性:同一时间只有一个线程可以获取到锁。
  2. 可重入性:线程可以多次获取同一个锁,不会造成死锁。
  3. 公平性:可以选择公平锁或非公平锁。公平锁按照线程的申请顺序获取锁,而非公平锁不保证线程获取锁的先后顺序。
  4. 中断响应性:支持线程的中断响应,即当一个线程等待获取锁时,可以通过中断该线程来使其放弃等待。
  5. 条件变量:提供了Condition接口,可以通过条件变量实现线程的等待和唤醒机制。

实现:

ReentrantLock的实现是基于AQS(AbstractQueuedSynchronizer)的,它使用一个FIFO的等待队列来管理线程的等待和唤醒。

原理:

知识跳转(AQS和CAS)

  1. ReentrantLock通过CAS(Compare and Swap)操作来实现对锁状态的修改和判断。
  2. 当一个线程获取锁时,如果锁是空闲状态,它会直接获取到锁;如果锁被其他线程持有,当前线程会进入等待队列。
  3. 当一个线程释放锁时,会唤醒等待队列中的一个线程来获取锁。
  4. ReentrantLock内部维护了一个状态变量state,用来记录锁的状态和重入次数。

与synchronized的异同:

异同之处如下:

  1. ReentrantLock是一个类,而synchronized是Java的关键字。
  2. ReentrantLock提供了更多的功能,如可重入性、公平性、中断响应性和条件变量等,而synchronized只提供了基本的同步功能。
  3. ReentrantLock需要手动获取和释放锁,而synchronized由JVM自动管理锁的获取和释放。
  4. ReentrantLock可以选择公平锁或非公平锁,而synchronized只能使用非公平锁。
  5. ReentrantLock的性能相对较好,但使用时需要注意手动释放锁,否则可能导致死锁。synchronized的性能相对较低,但使用更简单,且能自动释放锁。

5、volatile关键字

用于修饰变量。它具有以下特性和功能:

概念:

  1. 可见性:被volatile修饰的变量对所有线程可见,当一个线程修改了volatile变量的值,其他线程可以立即看到这个变化。
  2. 禁止指令重排序:volatile关键字禁止编译器和处理器对指令进行重排序,保证了代码的有序性。

功能:

  1. 在多线程环境下保证变量的可见性。当一个线程修改了volatile变量的值,其他线程可以立即看到这个变化。
  2. 禁止指令重排序,保证代码的有序性。

实现原理:

  1. 可见性:在JVM中,volatile关键字通过使用内存屏障(Memory Barrier)来实现可见性。内存屏障会强制刷新处理器缓存并写入主内存,以使得其他线程能够读取最新的值。
  2. 禁止指令重排序:volatile关键字会限制编译器和处理器对指令进行重排序,保证代码的执行顺序。

与synchronized的异同:

  1. 相同点:都可以用于多线程环境下的同步,保证共享资源的安全访问。
  2. 不同点:
    • synchronized是重量级锁,会自动进行加锁和释放锁的操作,而volatile只保证可见性和禁止指令重排序。
    • synchronized可以修饰方法、代码块和类,而volatile只能修饰变量。
    • synchronized可以实现互斥锁,保证同一时间只有一个线程可以执行被修饰的代码块,而volatile不能实现互斥锁。
    • synchronized可以解决线程的安全性和有序性问题,而volatile只能解决有序性问题。

你可能感兴趣的:(Java随笔,1024程序员节)