MST

星途 面试题库

面试题:Java静态变量与静态方法在多线程环境下的表现

在多线程并发访问的场景中,Java的静态变量和静态方法会出现哪些问题?如何确保静态变量在多线程环境下的线程安全?请结合实际代码说明同步机制(如synchronized关键字、锁等)在这种场景下的应用。
33.5万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

多线程并发访问Java静态变量和静态方法的问题

  1. 数据不一致问题:多个线程同时访问和修改静态变量时,可能会导致数据不一致。因为线程的执行顺序是不确定的,可能会出现一个线程读取了静态变量的值,然后另一个线程修改了该值,第一个线程再进行操作时,使用的就是过期的数据。
  2. 竞态条件(Race Condition):静态方法如果涉及对静态变量的操作,在多线程环境下也会出现竞态条件。多个线程竞争对静态变量的操作权,导致程序运行结果不可预测。

确保静态变量在多线程环境下线程安全的方法

  1. 使用synchronized关键字
    • 修饰静态方法:当synchronized修饰静态方法时,锁对象是该类的Class对象。所有线程访问该静态方法时,需要获取该类的Class对象的锁。
    public class StaticThreadSafeExample {
        private static int count = 0;
    
        public static synchronized void increment() {
            count++;
        }
    
        public static int getCount() {
            return count;
        }
    }
    
    • 修饰静态代码块:同样可以通过synchronized修饰静态代码块来保证线程安全,锁对象同样是该类的Class对象。
    public class StaticThreadSafeExample2 {
        private static int count = 0;
    
        static {
            synchronized (StaticThreadSafeExample2.class) {
                // 这里可以进行一些初始化操作,且线程安全
                count = 10;
            }
        }
    
        public static int getCount() {
            return count;
        }
    }
    
  2. 使用锁(Lock接口)java.util.concurrent.locks.Lock接口提供了更灵活的锁机制。可以使用ReentrantLock来保证静态变量的线程安全。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class StaticThreadSafeWithLock {
    private static int count = 0;
    private static final Lock lock = new ReentrantLock();

    public static void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

    public static int getCount() {
        return count;
    }
}

在上述代码中,ReentrantLock保证了在同一时间只有一个线程可以执行increment方法中修改静态变量count的代码,从而确保了线程安全。在使用Lock时,需要注意在try - finally块中进行加锁和解锁操作,以避免异常情况下锁未释放的问题。