乐观锁和悲观锁

点击量:1117

这两个概念是非常宏观的,只是两种不同的设计思想。

一、基本概念

悲观锁:假设线程在竞争资源时肯定会发生冲突,这时就需要把这个资源锁住,只有一个线程能同时操作这些竞争资源,其他线程只能等待拥有这个锁的线程完成操作。

乐观锁:顾名思义就是假设线程在竞争资源不会发生冲突,或者说概率很小,大家都可以同时访问这个资源,只有在最终修改的那一瞬间才会去检查是否能够修改。但如果发现冲突了怎么办?回滚。

这样很明显,乐观锁加锁的时间短,在多读少写,并发的可能性较低的情况下,可以减少事务之间的锁等待和事务对锁的管理开销,能够在一定程度上提高效率。但如果在资源竞争很激烈的情况下,乐观锁就会因为频繁的回滚导致性能的下降。

乐观锁的最初概念其实是Optimistic concurrency control,最初由华人科学家H. T. Kung在1981年提出,wikipedia给出的定义非常准确:

Optimistic concurrency control (OCC) is a concurrency control method applied to transactional systems such as relational database management systems and software transactional memory. OCC assumes that multiple transactions can frequently complete without interfering with each other. While running, transactions use data resources without acquiring locks on those resources. Before committing, each transaction verifies that no other transaction has modified the data it has read. If the check reveals conflicting modifications, the committing transaction rolls back and can be restarted.[1] Optimistic concurrency control was first proposed by H.T. Kung.[2]

OCC is generally used in environments with low data contention. When conflicts are rare, transactions can complete without the expense of managing locks and without having transactions wait for other transactions’ locks to clear, leading to higher throughput than other concurrency control methods. However, if contention for data resources is frequent, the cost of repeatedly restarting transactions hurts performance significantly; it is commonly thought that other concurrency control methods have better performance under these conditions. However, locking-based (“pessimistic”) methods also can deliver poor performance because locking can drastically limit effective concurrency even when deadlocks are avoided.

二、乐观锁的应用

乐观锁最常见的应用是在Hibernate中更新记录时会通过一个version字段来记录本条记录的最新状态,比如原本数据库里version的值是3,更新提交应该是3+1=4,如果相等则可以更新,否则回滚或者返回失败。

三、实现方式

乐观锁本质上也是加锁,只不过粒度要小很多,他锁的不是这个资源,而是资源在更改那一瞬间的状态,这便是是乐观锁的本质。Jboss的官方文档对这一点作出了如下解释:

Transactional isolation is usually implemented by locking whatever is accessed in a transaction. There are two different approaches to transactional locking: Pessimistic locking and optimistic locking.

The disadvantage of pessimistic locking is that a resource is locked from the time it is first accessed in a transaction until the transaction is finished, making it inaccessible to other transactions during that time. If most transactions simply look at the resource and never change it, an exclusive lock may be overkill as it may cause lock contention, and optimistic locking may be a better approach. With pessimistic locking, locks are applied in a fail-safe way. In the banking application example, an account is locked as soon as it is accessed in a transaction. Attempts to use the account in other transactions while it is locked will either result in the other process being delayed until the account lock is released, or that the process transaction will be rolled back. The lock exists until the transaction has either been committed or rolled back.

With optimistic locking, a resource is not actually locked when it is first is accessed by a transaction. Instead, the state of the resource at the time when it would have been locked with the pessimistic locking approach is saved. Other transactions are able to concurrently access to the resource and the possibility of conflicting changes is possible. At commit time, when the resource is about to be updated in persistent storage, the state of the resource is read from storage again and compared to the state that was saved when the resource was first accessed in the transaction. If the two states differ, a conflicting update was made, and the transaction will be rolled back.

In the banking application example, the amount of an account is saved when the account is first accessed in a transaction. If the transaction changes the account amount, the amount is read from the store again just before the amount is about to be updated. If the amount has changed since the transaction began, the transaction will fail itself, otherwise the new amount is written to persistent storage.

出自:https://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/TransactionJTA_Overview-Pessimistic_and_optimistic_locking.html

常见的实现方式是CAS(Compare And Swap),是一种更新的原子操作,比较当前值跟传入值是否一样,一样则更新,否则失败。如果不使用CAS自己加锁也是可以的。

     

原创不易,如果您觉得本文对您有帮助,可以打赏博主一杯咖啡,鼓励博主持续创作!


  • Ethereum/Polygon/Bsc/Arbitrum: 0xa8c00949fd7dD23b5Ec36A9181966c8C8436A015
  • Bitcoin: bc1qdvf0j0rntarvdal62n35etwmjzwk307w4jtyjz
  •    
  • 支付宝:

  • 发表评论

    邮箱地址不会被公开。 必填项已用*标注