静态方法没有任何参数线程安全吗?

时间:2014-02-26 01:09:28

标签: java multithreading

我有一个计数器,多个线程访问getCount方法。代码如下:

public class ThreadSafeMethod {

        public static int counter = 0;

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

方法线程安全吗?我的理解是,因为counter++不是自动的,所以不安全。那怎么安全呢?如果我们添加synchronized关键字,将同步哪个对象?

4 个答案:

答案 0 :(得分:5)

当你说它不是线程安全的时,你的分析是正确的,因为操作不是原子的。检索值和增量不是线程安全的。对此方法的多次调用(无论是否有参数)都可以访问相同的非局部变量。

向此方法添加synchronized使其具有线程安全性。添加到static方法时,Class对象是被锁定的对象。

使其成为线程安全的替代方法是将int替换为AtomicInteger,{{1}}具有自己的原子getAndIncrement方法。

答案 1 :(得分:3)

,无参数方法本质上是线程安全的 - 缺少参数在此示例中没有区别。

counter变量的读取(并写入)保证在线程之间是原子一致

最简单的改变就是make the method synchronized

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

(最简单的并不总是“最好”或“正确”,但这里就足够了,假设没有其他代码触及公共counter变量。)

请参阅this answer了解静态方法的同步是如何工作的 - 可以想象,它本身就是用作监视器的类。

答案 2 :(得分:1)

在静态函数上使用synchronized关键字会将函数“锁定”到一个线程,以确保两个线程不会混淆同一个变量。根据您的建议,我相信在该函数中访问或修改的任何内容都是线程安全的。

答案 3 :(得分:1)

正如您所说counter++操作是非原子的,因此一次授予多个线程访问权限将导致未定义的行为。在线程安全性方面,问题几乎总是对共享资源(如静态变量)进行同步访问。

线程在声明方法synchronized时获取的锁属于该类。假设我们在一个类中有两个方法

public synchronized void foo() {...}
public synchronized void bar() {...}

如果一个帖子进入foo(),它会获取该类的锁定,而任何其他尝试访问foo() OR bar()的帖子都会阻止,直到第一个线程已经完成。为了解决这个问题,我们可以锁定方法中的单独对象。

// Declare 2 objects to use as locks within the class
private Object fooLock = new Object();
private Objecy barLock = new Object();

// lock on these objects within the method bodies
public void foo {
    synchronized(fooLock) { /* do foo stuff */ }
}

public void bar() {
    synchronized(barLock) {/* do bar stuff */}
}

现在,2个主题可以同时访问foo()bar()

网上有很多关于线程安全的资料,如果你想了解更多关于使用锁/执行器服务和东西的多线程,我会推荐this套教程。