同步静态方法在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 } 

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

所以你的假设是正确的。

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

不是真的。 你应该让这个工作来代替你的RDBMS。 他们擅长这种东西。

通过同步对数据库的访问,唯一的办法就是使应用程序非常慢。 更进一步,在你发布的代码中,你每次构build一个Session Factory,这样,你的应用程序将花费更多的时间访问数据库,而不是执行实际的工作。

想象一下下面的场景:

客户A和B试图在表T的loggingX中插入不同的信息。

通过你的方法,你唯一要做的就是确保一个是在另一个之后被调用的,当这个在DB中发生的时候,因为RDBMS会阻止他们同时从A中插入一半信息, 。 结果将是相同的,但只有5倍(或更多)慢。

可能最好看一下Hibernate文档中的“Transactions and Concurrency”一章。 大多数情况下,你正在努力解决的问题已经被解决,并且是一个更好的方法。

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

请记住,使用synchronized方法实际上只是简写(假设类是SomeClass):

 synchronized static void foo() { ... } 

是相同的

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

 synchronized void foo() { ... } 

是相同的

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

你可以使用任何对象作为锁。 如果你想locking静态方法的子集,你可以

 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) {...} } } 

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

静态方法使用这个类作为locking的对象,这个例子就是Utils.class。 所以是的,这是可以的。

static synchronized意味着对类的Class对象持有locking, synchronized意味着locking该类的对象本身。 这意味着,如果您正在一个线程(执行)中访问非静态同步方法,您仍然可以使用另一个线程访问一个静态同步方法。

所以,在任何时间通过多个线程访问两种相同的方法(两个静态方法或两个非静态方法)是不可能的。

为什么要强制只有一个线程可以在任何时候访问数据库?

数据库驱动程序的工作是实现任何必要的locking,假设Connection只能由一个线程使用!

很可能,您的数据库完全有能力处理多个并行访问

如果是与数据库中的数据有关,为什么不利用数据库隔离locking来实现?

要回答你的问题,是的:你的synchronized方法不能一次执行多个线程。