Java concurrent programming-optimistic locking & pessimistic locking

Concurrency control

When there may be concurrency in the program, we need to use certain means to ensure the accuracy of the data in the case of concurrency. This method ensures that the current user and other users operate together, and the results obtained are separate from him. The result of the operation is the same. This method is called concurrency control. The purpose of concurrency control is to ensure that the work of one user does not unreasonably affect the work of another user.

Failure to do concurrency control can lead to problems such as dirty reads, phantom reads, and non-repeatable reads.

The concurrency control we often say is generally related to the database management system (DBMS). The task of concurrency control in the DBMS is to ensure that when multiple transactions access the same data in the database at the same time, the isolation and unity of the transactions and the unity of the database are not destroyed.

 

Means of achieving concurrency control

The main means of achieving concurrency control can be roughly divided into optimistic concurrency control and pessimistic concurrency control.
Before starting the introduction, it should be clear: whether it is a pessimistic lock or an optimistic lock, it is a concept defined by people and can be considered as an idea. In fact, not only the relational database system has the concepts of optimistic locking and pessimistic locking, like hibernate, tair, memcache, etc. have similar concepts. Therefore, optimistic locks, pessimistic locks, and other database locks should not be compared.

 

Pessimistic Lock

When we want to modify a piece of data in a database, in order to avoid being modified by others at the same time, the best way is to directly lock the data to prevent concurrency. This method of using a database lock mechanism to lock before modifying data is called pessimistic concurrency control (also known as "pessimistic lock", Pessimistic Concurrency Control, abbreviation "PCC").

Baidu Encyclopedia

Pessimistic locks, as the name suggests, have strong exclusive and exclusive characteristics. It refers to a conservative attitude to the data being modified by the outside world (including other current transactions of the system and transaction processing from external systems). Therefore, in the entire data processing process, the data is in a locked state. The implementation of pessimistic locks often depends on the lock mechanism provided by the database (only the lock mechanism provided by the database layer can truly guarantee the exclusivity of data access, otherwise, even if the lock mechanism is implemented in this system, there is no guarantee that the external system will not be modified data).

The reason why it is called pessimistic locking is because it is a concurrency control method that has a pessimistic attitude towards data modification. We generally think that the probability of data being modified concurrently is relatively high, so we need to lock before modifying.

Pessimistic locks are mainly shared or exclusive locks

  • Shared lock is also called read lock, or S lock for short. As the name implies, shared locks mean that multiple transactions can share a lock for the same data and can access the data, but can only read it and cannot modify it.
  • Exclusive locks are also called write locks, or X locks for short. As the name implies, exclusive locks cannot coexist with other locks. If a transaction acquires an exclusive lock for a data row, other transactions can no longer acquire other locks for that row, including shared locks and exclusive locks, but transactions that acquire exclusive locks are possible. Read and modify data rows.

Pessimistic concurrency control is actually a conservative strategy of "fetch lock before access", which provides a guarantee for the security of data processing.

But in terms of efficiency, the mechanism of handling locking will cause additional overhead for the database and increase the chance of deadlock. In addition, it will reduce the parallelism. If a transaction locks a row of data, other transactions must wait for the transaction to complete before processing that row of data.

 

Optimistic Locking (Optimistic Locking)

Optimistic locking is relative to pessimistic locking. Optimistic locking assumes that data will not cause conflicts under normal circumstances, so when data is submitted for update, it will formally check whether the data conflicts or not. If a conflict is found, return Give the user the wrong information and let the user decide how to do it.

Baidu Encyclopedia

The optimistic locking mechanism has adopted a more relaxed locking mechanism. Optimistic locks are relatively pessimistic locks, and are also a mechanism to avoid data processing errors caused by database phantom reads and excessive business processing time. To ensure the accuracy of the data.

Compared with pessimistic locking, optimistic locking does not use the locking mechanism provided by the database when processing the database. The general way to achieve optimistic locking is to record the data version.

Optimistic concurrency control believes that the probability of data races between transactions is relatively small, so it should be done directly as much as possible, and it will not be locked until it is committed, so no locks or deadlocks will occur.

 

Method to realize

Pessimistic lock implementation

The realization of pessimistic locking often relies on the locking mechanism provided by the database. In the database, the process of pessimistic locking is as follows:

  1. Before modifying the record, try to add exclusive locking to the record.
  2. If the lock fails, the record is being modified, so the current query may have to wait or throw an exception. The specific response method is determined by the developer according to actual needs.
  3. If the lock is successfully added, the record can be modified and the transaction will be unlocked after the transaction is completed.
  4. In the meantime, if there are other operations that modify the record or add an exclusive lock, we will wait for us to unlock or directly throw an exception.

Take the commonly used MySql Innodb engine as an example to illustrate how to use pessimistic locking in SQL.

To use pessimistic locking, we must turn off the automatic commit property of the MySQL database. Because MySQL uses autocommit mode by default, that is, when we perform an update operation, MySQL will immediately submit the results. (Sql statement: set autocommit = 0)

To illustrate the use of pessimistic locks with the need to deduct inventory during Taobao ’s order placement:

As above, before modifying the record with id = 1, first lock it by means of for update, and then modify it. This is the more typical pessimistic locking strategy.

If the above code to modify the inventory occurs concurrently, only one thread can open the transaction and obtain the lock with id = 1 at the same time. Other transactions must wait for the transaction to be submitted for execution. This way we can guarantee that the current data will not be modified by other transactions.

As we mentioned above, using select ... for update will lock the data, but we need to pay attention to some lock levels, MySQL InnoDB default row-level lock. Row-level locks are based on indexes. If an SQL statement cannot use an index, row-level locks will not be used. Table-level locks will be used to lock the entire table. This needs attention.

Optimistic locking implementation

The use of optimistic locking does not require the use of database locking mechanisms.

The concept of optimistic locking has actually elaborated its specific implementation details. There are two main steps: conflict detection and data update. There is a more typical way of its implementation is CAS (Compare and Swap).

CAS is an optimistic locking technology. When multiple threads try to use CAS to update the same variable at the same time, only one of the threads can update the value of the variable, and the other threads fail. Inform the failure of this competition and try again.

For example, the previous inventory deduction problem can be achieved through optimistic locking as follows:

Above, before we update, we first check the current inventory quantity (quantity) in the inventory table, and then when updating, use the inventory quantity as a modification condition. When we submit an update, we judge that the current inventory number of the corresponding record in the database table is compared with the number of inventory that was taken out for the first time. Otherwise, it is considered to be outdated data.

The above update statement has a more important problem, namely the legendary ABA problem .

For example, if one thread one takes inventory number 3 from the database, then another thread two also takes inventory number 3 from the database, and two performs some operations to become 2, and then two turns the inventory number into 3 again. When the thread one performs the CAS operation, it is found that the database is still 3, and then the one operation is successful. Although the CAS operation of thread one is successful, it does not mean that this process is not a problem.

There is a better way to solve the ABA problem, that is, through a single version field that can be sequentially incremented. Change to the following method:

Every time optimistic locking performs a data modification operation, it will bring a version number. Once the version number and the data version number are consistent, you can perform the modification operation and perform a +1 operation on the version number, otherwise the execution fails. Because the version number of each operation will increase accordingly, there will be no ABA problem, because the version number will only increase and not decrease.

In addition to version, you can also use timestamps, because timestamps are naturally increasing in order.

In fact, the above SQL still has certain problems. Once high concurrency is encountered, only one thread can be modified successfully, and then there will be a large number of failures.

For e-commerce sites like Taobao, high concurrency is a common occurrence, and it is obviously unreasonable to always let users perceive failure. Therefore, we still have to find ways to reduce the granularity of optimistic locking.

There is a better suggestion, which can reduce the optimistic locking strength, maximize the throughput rate, and improve the concurrency! as follows:

In the above SQL statement, if the number of orders placed by the user is 1, then optimistic lock control is performed by means of quantity-1> 0.

During the execution of the above update statement, it will query the value of the quantity in an atomic operation and deduct it by 1.

Lock granularity control is an important subject in a high concurrency environment. Choosing a good lock can greatly increase the throughput rate and the performance while ensuring data security.

 

how to choose

In the choice of optimistic locking and pessimistic locking, mainly look at the difference between the two and the applicable scenarios.

  1. Optimistic locking does not really lock, and is highly efficient. Once the granularity of the lock is not well grasped, the probability of update failure will be relatively high, and business failure is prone to occur.

  2. Pessimistic locks rely on database locks and are inefficient. The probability of update failure is relatively low.

With the proposition of the Internet's three high architectures (high concurrency, high performance, and high availability), pessimistic locks have been used less and less in production environments, especially in business scenarios with relatively large concurrent volumes.

1005 original articles published · 1890 praised · 900,000 views

Guess you like

Origin blog.csdn.net/Dream_Weave/article/details/105538696