小编典典

同步静态方法在Java中如何工作?

java

如果我有一个带有静态方法的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
}

阅读 342

收藏
2020-03-15

共2个答案

小编典典

通过在静态方法锁上使用sync,你将同步类的方法和属性(与实例方法和属性相对)

所以你的假设是正确的。

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

并不是的。你应该让该工作代替你的RDBMS。他们擅长这类东西。

同步对数据库的访问将获得的唯一结果就是使你的应用程序非常慢。此外,在你发布的代码中,每次都在构建会话工厂,这样,与执行实际工作相比,你的应用程序将花费更多的时间访问数据库。

想象以下情况:

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

使用你的方法,唯一得到的就是确保在数据库中无论如何都会发生一个被另一个调用的情况,因为RDBMS会阻止它们同时从A插入一半信息,从B插入一半信息。 。结果将相同,但仅慢5倍(或更多)。

也许最好看看Hibernate文档中的“事务和并发性”一章。在大多数情况下,你要解决的问题已经得到解决,并且是一种更好的方法。

2020-03-15
小编典典

为了更一般地解决这个问题…

请记住,在方法上使用同步实际上只是简写(假设类是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) {...}
    }
}

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

2020-03-15