简体   繁体   English

使方法同步将确保它是线程安全的吗?

[英]Is making a method synchronized will ensure that it is thread safe?

I have a method in which some database insert operations are happening using hibernate and i want them to be thread safe. 我有一种方法,其中一些数据库插入操作正在使用休眠进行,我希望它们是线程安全的。 The method is getting some data in parametres and its a possiblity that sometimes two calls are made with same data at same point of time. 该方法以参数为单位获取某些数据,并且有可能有时在同一时间点使用相同数据进行两次调用。

I can't lock those tables because of performance degradation. 由于性能下降,我无法锁定这些表。 Can anyone suggest making the method as synchronized will solve issue? 谁能建议使该方法成为同步方法可以解决问题?

Synchronizing a method will ensure that it can only be accessed by one thread at a time. 同步方法将确保一次只能由一个线程访问该方法。 If this method is your only means of writing to the database, then yes, this will stop two threads from writing at the same time. 如果此方法是您写入数据库的唯一方法,那么可以,这将阻止两个线程同时写入。 However, you still have to deal with the fact that you have multiple insert operations with the same data. 但是,您仍然必须处理这样一个事实,即您需要对同一数据执行多个插入操作。

You should let Hibernate handle the concurrency, that's what it is meant to do. 您应该让Hibernate处理并发,这就是要做的事情。 Don't assume Hibernate will lock anything: it supports optimistic transactions for exactly this purpose. 不要以为Hibernate会锁定任何东西:为此,它支持乐观事务 Quote from the above link: 从以上链接引用:

The only approach that is consistent with high concurrency and high scalability, is optimistic concurrency control with versioning. 与高并发性和高可伸缩性一致的唯一方法是通过版本控制进行乐观并发控制。 Version checking uses version numbers, or timestamps, to detect conflicting updates and to prevent lost updates. 版本检查使用版本号或时间戳来检测冲突的更新并防止更新丢失。 Hibernate provides three possible approaches to writing application code that uses optimistic concurrency. Hibernate提供了三种使用乐观并发编写应用程序代码的方法。

Database Concurrency is handled by transactions. 数据库并发由事务处理。 Transactions have the Atomic Consistent Isolated Durable (ACID) properties. 事务具有“原子一致性持久隔离(ACID)”属性。 They provide isolation between programs accessing a database concurrently. 它们提供了并发访问数据库的程序之间的隔离。 In the Hibernate DAO template of spring framework there are single line methods for CRUD operations on the database. 在spring框架的Hibernate DAO模板中,有用于数据库上CRUD操作的单行方法。 When used individually these don't need to be synchronized by method. 单独使用时,不需要按方法进行同步。 Spring provides declarative (XML), programmatic and annotation meta-data driven transaction management if you need to declare "your method" as transactional with specific propagation settings, rollbackFor settings, isolation settings. 如果您需要使用特定的传播设置,rollbackFor设置,隔离设置将“您的方法”声明为事务性的,则Spring提供了声明式(XML),程序化和注释元数据驱动的事务管理。 So in "your method" you can do multiple save,update,deletes etc and the ORM will ensure that it is executed with the transaction settings you have given in the meta-data. 因此,在“您的方法”中,您可以进行多次保存,更新,删除等操作,并且ORM将确保使用您在元数据中给定的事务设置执行该操作。

Another issue is that the thread has to have the lock on all the objects that are taking part in the transaction.Otherwise the transaction might fail or the ORM will persist stale data. 另一个问题是线程必须锁定参与事务的所有对象,否则事务可能会失败或ORM将保留陈旧数据。 In another situation it can result in a deadlock because of lock-ordering. 在另一种情况下,由于锁定顺序,可能导致死锁。 I think this is what really answers your question. 我认为这才是真正回答您问题的方法。

Both objects a and b have an instance variable of the type Lock. 对象a和b都有一个Lock类型的实例变量。 A boolean flag can be used to indicate the success of the transaction. 布尔标志可用于指示交易成功。 The client code can retry the same transaction if it fails. 如果客户端代码失败,则可以重试同一事务。

             if (a.lock.tryLock()) {
                try {
                    if (b.lock.tryLock()) {
                        try {
                            // persist or update object a and b
                        } finally {
                            b.lock.unlock();
                        }
                    }
                } finally {
                    a.lock.unlock();
                }
            }

The problem with using synchronized methods is that it locks up the entire Service or DAO class making other service methods unavailable to other threads. 使用同步方法的问题在于,它锁定了整个Service或DAO类,从而使其他线程无法使用其他服务方法。 By using individual locks on objects we can gain the advantage of fine grained concurrency. 通过对对象使用单独的锁,我们可以获得细粒度并发的优势。

No. This method probably uses another methods and objects, which may be not thread safe. 不可以。此方法可能使用其他方法和对象,这些方法和对象可能不是线程安全的。 synchronized makes threads to use that's method's object monitor only once at a time, so it makes thread-safe a method with respect to the object. synchronized使线程一次只能使用该方法的对象monitor一次,因此它使线程安全的方法相对于该对象。

If you are sure that all other threads use shared functionality only with this method, then making it synchronized may be sufficient. 如果确定所有其他线程仅通过此方法使用共享功能,则使其synchronized可能就足够了。

Choosing the best strategy depends on the architecture, sometimes to increase performance seems to be easier to use the trick like method synchronization, but this is bad approach. 选择最佳策略取决于体系结构,有时使用方法同步之类的技巧来提高性能似乎更容易,但这是不好的方法。

There's no doubts, you should use transactions, and if with that strategy you're facing performance issues you should optimize your db queries or db structure. 毫无疑问,您应该使用事务,并且如果使用该策略遇到性能问题,则应该优化数据库查询或数据库结构。

Please remember that "Synchronization" should be as much as possible atomic. 请记住,“同步”应尽可能地原子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM