如何使 Java 中的方法线程安全?

原文地址:http://www.programcreek.com/2014/02/how-to-make-a-method-thread-safe-in-java/

一个面试问题:

以下方法线程安全吗? 如何使它线程安全?

class MyCounter {
    private static int counter = 0;

    public static int getCount() {
        return counter++;
    }
}

这是 Google 和许多其他公司经常提出的一个的面试问题。

首先,答案是否定的,该方法不是线程安全的,因为计数器累加操作不是原子性的,这意味着它包含多个原子操作。 在这种情况下,一个是访问该值,另一个是将值增加 1。

当线程 1 在 t1 访问方法时,线程 2 可能还没执行完该方法。 所以返回给线程 1 的值是没有增加的值。

使方法线程安全 - 方法 1

添加 synchronized 关键字到此方法将使其线程安全。 当 synchronized 被添加到静态方法时,Class 对象将被锁定。

标记一下就能实现同步? 答案是肯定的。

class MyCounter {
    private static int counter = 0;

    public static synchronized int getCount() {
        return counter++;
    }
}

如果该方法不是静态的,那么添加 synchronized 关键字将同步类的实例,而不是 Class 对象。

使方法线程安全 - 方法 2

在下面这个例子中,我们通过使用 java.util.concurrent.atomic 包中的 AtomicInteger 来创建 count++ 原子。

import java.util.concurrent.atomic.AtomicInteger;

public class MyCounter {
    private static AtomicInteger counter = new AtomicInteger(0);

    public static int getCount() {
        return counter.getAndIncrement();
    }
}

关于线程安全的一些有用的常识

  • 局部变量在 Java 中是线程安全的。

  • 每个线程都有自己的堆栈,两个不同的线程不会共用同一个堆栈。 在方法中定义的所有局部变量将被分配给堆栈内存,当前线程一旦执行完该方法,堆栈帧将被删除。

results matching ""

    No results matching ""