同步静态方法在Java中如何工作,我可以使用它来加载Hibernate实体吗?

如果我有一个具有静态方法的util类,它将调用Hibernate函数来完成基本的数据访问。我想知道制作该方法是否是确保线程安全的正确方法。synchronized

我希望这样可以防止信息访问同一数据库实例。但是,我现在确定以下代码是否在被特定类调用时阻止对所有类进行调用。getObjectById

public class Utils {
     public static synchronized Object getObjectById (Class objclass, Long id) {
           // call hibernate class
         Session session = new Configuration().configure().buildSessionFactory().openSession();
         Object obj = session.load(objclass, id);
         session.close();
         return obj;
     }

     // other static methods
}

答案 1

为了更广泛地解决这个问题...

请记住,使用同步方法实际上只是速记(假设类是SomeClass):

synchronized static void foo() {
    ...
}

与 相同

static void foo() {
    synchronized(SomeClass.class) {
        ...
    }
}

synchronized void foo() {
    ...
}

与 相同

void foo() {
    synchronized(this) {
        ...
    }
}

您可以使用任何对象作为锁定。如果要锁定静态方法的子集,可以

class SomeClass {
    private static final Object LOCK_1 = new Object() {};
    private static final Object LOCK_2 = new Object() {};
    static void foo() {
        synchronized(LOCK_1) {...}
    }
    static void fee() {
        synchronized(LOCK_1) {...}
    }
    static void fie() {
        synchronized(LOCK_2) {...}
    }
    static void fo() {
        synchronized(LOCK_2) {...}
    }
}

(对于非静态方法,您可能希望使锁成为非静态字段)


答案 2

通过在静态方法锁上使用synced,您将同步类方法和属性(而不是实例方法和属性)

所以你的假设是正确的。

我想知道使方法同步是否是确保线程安全的正确方法。

没有。您应该让RDBMS来完成这项工作。他们擅长这种东西。

通过同步对数据库的访问,您唯一能得到的就是使应用程序变得非常慢。此外,在您发布的代码中,您每次都会构建一个会话工厂,这样,您的应用程序将花费更多的时间来访问数据库而不是执行实际作业。

想象一下以下场景:

客户端 A 和 B 尝试将不同的信息插入到表 T 的记录 X 中。

通过您的方法,您唯一得到的就是确保一个在另一个之后被调用,而这在数据库中无论如何都会发生,因为RDBMS将阻止它们同时插入来自A的一半信息,以及来自B的一半信息。结果将是相同的,但只有5倍(或更多)慢。

也许最好看看Hibernate文档中的“事务和并发”一章。大多数时候,你试图解决的问题已经解决了,而且是一个更好的方法。


推荐