非同步静态方法中修改静态变量,是否存在线程安全的风险?

3

我有一个带有静态方法的类,该方法修改一个静态变量,这个方法需要同步以实现线程安全吗?

public final class IdManager {

    private static int noOfIdsInReserveCurrently = 100;   
    private static final AtomicInteger allotedUserIdsCount; 

    public static int getNewId(){
         noOfIdsInReserveCurrently--;
         ....
         return allotedUserIdsCount.incrementAndGet();
    }
}

这个方法是否应该被同步?

1个回答

8

目前这种写法肯定是不安全的。两个线程都可以读取变量的值,然后减少各自本地的副本,最后再同时写入。这会导致问题。

你可以使用同步机制(以及其他方面)来解决这个问题,但更好的方法是使用AtomicInteger,它专门为此类问题而设计。如果你只修改了这一个值,那就没问题;但如果你需要原子性地修改更多共享状态(例如一些“下一个ID”计数器以及未完成的ID数量),那么你需要非常小心地考虑不同的交错情况,或者改用同步块。


1
@JohanSjöberg:你所说的“线程存在于另一个类中”是什么意思?我的观点是,如果两个线程都读取100,减少后再写回99,那么就会进行两次“逻辑”减少,但总体结果将是不正确的(为99而不是98)。 - Jon Skeet
@JonSkeet:谢谢,正如你所猜测的那样,我在同一个类中还使用了另一个AtomicInteger对象(在我的问题中进行了更新),因此存在更多共享状态(你的第二个选项不太清楚),这个方法最好是同步的还是我应该将“noOfIdsInReserveCurrently”作为“AtomicInteger”? - Rajat Gupta
在这种情况下,如果我不确定,将该方法同步化会是一个更加安全的选择,对吗? - Rajat Gupta
@user:是的。不过你还需要查看其他访问该共享状态的地方。 - Jon Skeet
@LouisWasserman:同意,虽然我不是完全反对静态类型。只是大多数情况下... - Jon Skeet
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接