锁
锁是一种抽象概念,是一种思想。并发环境下,多个线程会对同一资源争抢,可能导致数据不一致的问题。因此,很多编程语言都引入了锁。
Java中的锁
互斥锁(悲观锁(有锁同步))
操作系统悲观地认为如果不严格同步线程调用,那么一定会产生异常,互斥锁将会将资源锁定,只供一个线程调用,阻塞其他线程(独占资源),该同步机制也称为悲观锁。
如synchronized代码块就是互斥锁的一种实现。
有些时候,同步代码快执行的耗时远远小于线程切换的耗时。所以在这种情况下,不想要让操作系统那么悲观,所以能不能不对共享资源进行锁定,也能对线程调用进行协调?
乐观锁(无锁同步)
上层的无锁线程同步依赖的是CPU底层的CAS操作。
CAS(compare and swap)算法:
当资源对象的状态值符合要求,多条线程中的每条线程各自产生两个值,old value(之前读到的资源对象状态值),new value(想要将资源对象的状态值更新后的值)。
前一线程抢占到资源后,后一线程进行自旋(不断重试CAS操作),同时配置自旋次数防止死循环。
前提:CS必须是原子性的(由CPU底层指令架构支持)。
因此产生了一系列通过CAS来实现同步的工具,这些工具不会锁定资源,而且线程需要修改共享资源时,会乐观地认为对象状态值没有被其他线程修改过,主动尝试去compare状态值,该同步机制称为乐观锁。
(所以乐观锁更准确地应称为无锁同步)
MySQL中的锁
数据库并发场景有三种:读-读、读-写、写-写。
数据库中的乐观锁更倾向叫乐观并发控制(OCC),悲观锁叫悲观并发控制(PCC)。
不要把乐观锁和悲观锁与数据库中的行锁,表锁,排他锁,共享锁混为一谈,他们并不是一个维度的东西;前者是一种思想,后者是具体实现。
MySQL中悲观锁的实现
- 外界要访问某条数据,那它就要首先向数据库申请该数据的锁(某种锁)。
- 如果获得成功,那它就可以操作该数据,在它操作期间,其他客户端就无法再操作该数据了。
- 如果获得失败,则代表同一时间已有其他客户端获得了该锁,那就必须等待其他客户端释放锁。
数据库提供了非常多的锁,每种数据库提供的锁也不尽相同,所以具体情况就要看是什么锁了。MySQL中的行锁,表锁是悲观锁的具体实现之一。
优点
适合写多读少或读写都频繁的场景。
缺点
加锁增加系统开销,降低数据吞吐量。
MySQL中乐观锁的实现
假设认为在各类并发环境中,外界对数据的操作一般是不会造成冲突的,所以并不加锁,而是基于版本控制,采用类似Java中无锁同步所采用的CAS算法。
适合读多写少的场景。
标签:同步,悲观,CAS,线程,状态值,MySQL,分布式 From: https://www.cnblogs.com/fallorange/p/17710238.html