当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《同步静态方法如何在Java中工作?》经验,为你挑选了5个好方法。

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

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



1> Scott Stanch..:

更一般地解决这个问题......

请记住,使用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) {...}
    }
}

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


前4个代码块是黄金.正是我在寻找什么.谢谢.
@Samuel - 几乎......它更多地是关于线程而不是对象实例.你是正确的,因为SomeClass的单​​独实例都将使用相同的锁/监视器:与Someclass.class对象关联的那个.因此,如果两个不同的线程正在处理SomeClass的两个不同实例,则它们都无法同时运行.但是,如果单个线程在SomeClass的一个实例中调用了一个方法,并且该方法在另一个实例中调用了一个方法,则不会发生阻塞.

2> OscarRyz..:

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

所以你的假设是正确的.

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

并不是的.您应该让这项工作代替您的RDBMS.他们擅长这种东西.

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

想象一下以下场景:

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

使用你的方法你唯一得到的就是确保一个接一个地被调用,当这种情况在DB中发生时,因为RDBMS将阻止它们同时从A插入一半信息和从B插入一半信息.结果将相同,但只会慢5倍(或更多).

看看Hibernate文档中的"Transactions和并发"一章可能会更好.大多数时候,你试图解决的问题已经解决,并且已经有了更好的解决方法.


任何快餐店都使用多线程.一个线程会接受您的订单并使用另一个线程来准备它,并继续下一个客户.同步点仅在交换信息以了解准备内容时才起作用.遵循这样的模型真的简化了生活.
"全班"不是**被锁定.[Java机器语言规范](http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.3.6):`对于类(静态)方法,使用与方法类的Class对象关联的监视器.对于实例方法,使用与此关联的监视器(调用该方法的对象).因此,如果一个线程进入静态方法,则由[Object#getClass]返回相同的**对象**(http: //docs.oracle.com/javase/7/docs/api/java/lang/Object.html#getClass())已被锁定.其他线程仍然可以访问实例方法.
大声笑我发现我自己的措辞也不是最终正确的.我说"因此,如果一个线程进入静态方法,则Object#getClass返回的同一个对象被锁定".技术上不正确.长篇故事对所有好奇的人都很简单:对于你的应用程序中的每个类,都存在一个`Class`对象,由一个虚拟机类加载器实例化.像所有对象一样,这个对象也有一个与它关联的`Monitor`.而这台**显示器**正被锁定.

3> starblue..:

静态方法使用类作为锁定对象,例如Utils.class.是的,没关系.



4> prasad..:

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

因此,不可能在任何时间点通过多个线程访问两种相同类型的方法(两种静态方法或两种非静态方法).



5> oxbow_lakes..:

为什么要强制执行一次只有一个线程可以访问数据库?

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

最有可能的是,您的数据库完全能够处理多个并行访问

推荐阅读
女女的家_747
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有