锁存在的意义
在并发环境中,如果有多个线程对某项资源同时进行“写”操作,那么就可能会出现常说的“并发问题”,数据的一致性会被破坏。这时候,需要锁,来防止这种情况发生。锁本质上是限制了多个线程对同一资源在同一时间进行写操作。要实现这个限制,常规的有两种级别: 乐观并发控制和悲观并发控制。
悲观锁与乐观锁
”悲观“是假设: 我在修改数据的时候,一定会有其他人也来改,这样必会导致数据不一致。为了防止别人在我改数据的时候也来捣乱,那么就设计一套机制: 要修改某个数据,先得对这个数据加锁,加锁成功后才能进行操作,加锁失败则就等着别人处理完了再来获取锁。 只有获取到锁的的人,才能进行操作,操作完毕后就把锁释放掉,让下一个继续。
用人话说就是: 我在修改数据的时候你走开,等我处理完了你再来。
悲观锁需要对资源进行锁定,强制所有的操作串行化。串行化的过程中会有加锁/释放锁的消耗。
“乐观”是假设我在修改数据的时候没人会来捣乱,所以我不锁定数据,直接修改数据。如果我发现别人也在修改,那么我自动放弃本次操作,不在“同一时刻”对资源进行操作。
用人话说就是: 我准备改数据,但如果我发现你刚改完,那么我就不改了。
悲观锁可以锁定资源来实现,那么乐观锁怎么实现“你刚改完,那么我就不改了”呢?
常规的办法是通过“版本控制”。 每一次实际的更新操作对应着数据的一个版本变化,从一个旧版本到新版本。
比如,这项资源有个version字段,每次成功更新这个字段都会加1。 每次更新都是在一个旧版本