如果我有一个带有静态方法的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 }
Scott Stanch.. 226
更一般地解决这个问题......
请记住,使用synchronized on方法实际上只是简写(假设类是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) {...} } }
(对于非静态方法,您可能希望将锁定为非静态字段)
更一般地解决这个问题......
请记住,使用synchronized on方法实际上只是简写(假设类是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) {...} } }
(对于非静态方法,您可能希望将锁定为非静态字段)
通过在静态方法锁上使用synchronized,您将同步类方法和属性(而不是实例方法和属性)
所以你的假设是正确的.
我想知道是否使方法同步是确保线程安全的正确方法.
并不是的.您应该让这项工作代替您的RDBMS.他们擅长这种东西.
通过同步对数据库的访问,您将获得的唯一一件事就是使您的应用程序非常慢.此外,在您发布的代码中,您每次都在构建会话工厂,这样,您的应用程序将花费更多时间访问数据库,而不是执行实际工作.
想象一下以下场景:
客户端A和B尝试将不同的信息插入表T的记录X.
使用你的方法你唯一得到的就是确保一个接一个地被调用,当这种情况在DB中发生时,因为RDBMS将阻止它们同时从A插入一半信息和从B插入一半信息.结果将相同,但只会慢5倍(或更多).
看看Hibernate文档中的"Transactions和并发"一章可能会更好.大多数时候,你试图解决的问题已经解决,并且已经有了更好的解决方法.
静态方法使用类作为锁定对象,例如Utils.class.是的,没关系.
static synchronized
意味着对类的Class
对象
synchronized
持有锁定,这意味着锁定该类的对象本身.这意味着,如果要访问(执行)线程中的非静态同步方法,您仍然可以使用另一个线程访问静态同步方法.
因此,不可能在任何时间点通过多个线程访问两种相同类型的方法(两种静态方法或两种非静态方法).
为什么要强制执行一次只有一个线程可以访问数据库?
实现任何必要的锁定是数据库驱动程序的工作,假设一次Connection
仅由一个线程使用!
最有可能的是,您的数据库完全能够处理多个并行访问