Concurrent database operations and synchronized usage

Source: Internet
Author: User

Recently, the function of writing and review the database. When generating the library file, you need to obtain the file batch number (VOUCH_NO) from the database ). This operation requires mutual exclusion. I simulated this situation on my computer. I created a SYS_PARAM table in MySQL on the local machine and copied the SysParamUtil class and the company-encapsulated class library to the project. The following transaction control internal code simulates the implementation of the FileLogQueryBo. genFileLog () method in the ess project (the transaction control code is used to simulate AOP transaction control in the ess ).

 GetVouchNo   SysParamDao sysParamDao =  = + " transaction begin!"== (bean vouchNo =                vouchNo += 1                sysParamDao.makePersistent(bean,  (!+ " transaction commit!"(! (!   =  Thread(=  Thread("Thread 1""Thread 2"

When I saw this code on Friday, I thought it was possible to produce "Lost Update" (loss of updates) [see Head First Java P512]. At that time, I thought that if there are two operators A and B (which can be replaced by two threads), B enters the synchronization code block (synchronized) and updates the batch number in the database, at this time, the batch number obtained by A outside the synchronization block is stillOld. Today, after my experiment, I found that.In the experiment, I found thatA. the bean in line B references the same object in the heap.(Because SysParmUtil. the getInstance () method calls the internal genSysParam () method to obtain all the records in the SYS_PARAM data table, the key-value form of bean> exists in the internal HashTable. Therefore, B's modifications to bean in the synchronization block will be reflected in, that is to say, there is no "Lost Update" problem here, because the Update part is already in the synchronization block..However, the premise is that A and B threads are in the same Java Virtual Machine. If they are not in the same Java virtual machine, the program is distributed, then A and B cannot reference the same object in the same heap.I guess in the future, the e-creden project must be deployed on a host. The operator only needs to log on to the system through a browser to perform operations, therefore, the issue of concurrent review must occur only in the same Java virtual machine environment.

Let's take a look at the causes of concurrency problems described in Head First Java:

 

Multiple Threads simultaneously operate on the same object in the heap, which causes data inconsistency. The problem of obtaining and updating the batch number fully complies with the above definition: the same object (bean) in the heap of multiple threads (A and B) Operations (modifying the batch number ). To solve this problem, we need to bind multiple operations together as an inseparableAtomic operation. In the above Code, the following code must be bundled:Batch Number modification and persistenceOperation:

 vouchNo =                vouchNo += 1                sysParamDao.makePersistent(bean, );

Only after the makePersistent () (the Session. save () method of Hibernate is called internally) is executed to persist the bean can the bean modification be converted to the row modification in the database table.

 

Now that we know what operations to synchronize, it is important to consider which object to lock.

Synchronized usage

There are two synchronized keywords: one is written before the method header, and the other is written inside the method.No matter where it is written, its function is to lockThe only difference is that the lock object is different.Locking means that you need to get the lock of the locked object before entering the synchronized included area. If you cannot get the lock, you will not be able to get it. For example, if the above Code writes the synchronized keyword before the run method header,So we cannot achieve the purpose of mutual exclusion.. Why? Because synchronized is placed in the method header, the lock object is of the GetVouchNo class.InstanceEvery thread in the main function has its own GetVouchNo instance, so this lock has no effect. Unless you change the main function to the following:

  = = = "Thread 1""Thread 2"

 

In this case, the mutual exclusion can be achieved. At this time, each thread uses the same GetVouchNo instance. When a thread t1 enters the run method of the instance job, it needs to obtain the lock of the instance job. Then thread t2 can only wait outside, after t1 is executed and the lock is returned, t2 is eligible to enter the run method of the job. We can see that when synchronized is placed in the method header, the mutex range is too large. We only need to modify and persist the mutex batch number, so we can write synchronized inside the method:

 GetVouchNo   SysParamDao sysParamDao =   = + " transaction begin!"== ( vouchNo =                vouchNo += 1                sysParamDao.makePersistent(bean,  (!+ " transaction commit!"(! (!   = = = "Thread 1""Thread 2"

 

The above synchronized is written in the brackets behind it as the object to be locked,This indicates the current instance (the instance of GetVouchNo), which has the same effect as the method header written in synchronized.(Note that the main function code is different from the previous version.) The difference is that the synchronization scope is reduced, and only the synchronized block package statements are synchronized! This method is more flexible. Compare with the code at the top:

 vouchNo =        vouchNo += 1        sysParamDao.makePersistent(bean, 

 

The object to be locked here is bean, which means to get the bean lock when entering this code block. Because there is only one bean, there is only one lock, therefore, at the same time, only one thread can enter this region. This achieves the purpose of mutual exclusion! Another special feature is:Lock a class:

 (GetVouchNo. vouchNo =        vouchNo += 1        sysParamDao.makePersistent(bean, 

This indicates locking the GetVouchNo Class Object. Do not forget that the Class is also an object in Java, which is an object of java. lang. Class. In this case, even if the main function is written as follows:

  =  Thread(=  Thread("Thread 1""Thread 2"

It can also achieve mutex, because the GetVouchNo class object is locked, and only one class object exists, so there is only one lock, at the same time, only one thread can obtain the lock and enter the synchronization block.

Summary:

The synchronization and mutex in the above text are not strictly differentiated. the meaning to be expressed is that only one thread can operate bean at a time. In actual situations, synchronization and mutex are not both independent. In more cases, they are inseparable. Multiple Threads must modify the batch number (only one shared object exists in the heap) mutex. Therefore, only one lock exists in the system and the thread obtains the lock, which thread is eligible to modify the batch number.

 

2013.8.8 update

In the console, previous programs sometimes output Multiple SQL Select statements, and sometimes only one statement (Hibernate configures the output SQL statement). I feel very strange. Today I know why.SysParamUtil. genSysParam ()CalledSysParamDao. getAll ()It callsAbstractDaoImpl. getAll (), ThroughCriteria. list ()Query the database to obtain all records. The SELECT statement is generated at this time. SysParamUtil. genSysParam () is called only when the private member table is null in SysParamUtil. getInstance (). That is to say, it is called only when SysParamUtil. getInstance () is called for the first time. However, in a multi-threaded environment (such as the top code), multiple threads concurrently execute SysParamUtil. judge SysParamUtil when getInstance. whether the table is null. If it is null, SysParamUtil is called. genSysParam (). This process is not mutually exclusive. Therefore, the database is queried concurrently in multiple threads. This violates the principle that a single instance should be initialized only once., Will be thrownOrg. hibernate. NonUniqueObjectExceptionException I think it is a concurrent callAbstractDaoImpl. getAll (). The solution is to call SysParam. getInstance () to initialize the internal table when the thread is enabled; orSysParam bean = SysParamUtil. getInstance (). getSysParamByName (SysParamNameConst. VOUCH_NO );Put it inside the synchronization code block, so that the internal table will be initialized by the first thread that enters the synchronization block, and other incoming threads will no longer initialize it, in this way, no exception will be thrown after modification.

SysParamDao. getAll () is through Session. createCriteria () creates a Criteria, and then calls the Criteria list () method to query data records. I am thinking, Session. the object obtained by get () is persistent. Is the queried object persistent? After experiments, we found that the answer is yes. However, the Session responsible for creating Criteria is not closed after the list () method is called.Once the Session is closed, the object changes from the persistent state to the managed State (detached). Therefore, the key to whether an object is in a persistent state is to check whether it is associated with a Session and that Session is not closed..

Session. update (Object object)Whether the execution is successful depends on whether the id attribute (identifier, primary key of the data table) of the input parameter object exists, and a record with the same primary key value and id value must exist in the data table. That is to say, the object is in the new (transient State) or obtained through Session. get (persistent State) is not important!

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.