Lock

CAS:

  当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。   

  CAS 操作中包含三个操作数 —— 需要读写的内存位置(V)、进行比较的预期原值(A)和拟写入的新值(B)。如果内存位置V的值与预期原值A相匹配,那么处理器会自动将该位置值更新为新值B。否则处理器不做任何操作。无论哪种情况,它都会在 CAS 指令之前返回该位置的值。(在 CAS 的一些特殊情况下将仅返回 CAS 是否成功,而不提取当前值。)CAS 有效地说明了“ 我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。 ”这其实和乐观锁的冲突检查+数据更新的原理是一样的。

  乐观锁是一种思想。CAS是这种思想的一种实现方式。

===================

https://www.cnblogs.com/jyroy/p/11365935.html

锁记忆法:

  行锁 表锁 间隙锁;

  排他锁 共享锁;

  乐观锁来悲观锁;

  公不公平两把锁,二者均为重入锁;

  重量级别生四锁,无锁、偏向锁、轻量+重量级锁;

  最后再来个自旋锁。

======================================================

  行锁:mysql,锁定当前行,可以是S或X,会产生死锁,但是冲突概率较低,并发度高;

  表锁:mysql,锁定当前表,不会死锁,但性能很低;

  间隙锁:用于处理幻读问题,在c的左a右b范围内添加gap锁,防止其他线程插入c;

  排他锁(X):写锁,当前事务加锁后,其他事务无法加锁,但select * from t可拿到数据;

  共享锁(S):读锁,当前事务加锁后,其他事务也可以加S锁;

  乐观锁:执行写操作时先不加锁,两种方式version、CAS(存在ABA问题,解决ABA的办法是CAS+version);

  悲观锁:执行读写操作时先加锁;

  公平锁:排他锁+队列,当线程A释放锁时,其他众线程按照队列顺序获取锁,构造队列需要额外的开销;

  非公平锁:排他锁,当线程A释放锁时,其他众线程开始争夺锁,效率高,ReentrantLock默认为非公平锁;

  重入锁:排他锁+计数器,当前线程执行代码块时先加锁,当执行重入锁代码块时,jvm会判断当前锁的持有者是否为当前线程,if true=>count+1;else =>获取锁失败;

  无锁--偏向锁--轻量级锁--重量级锁:

    jvm根据线程对资源的争夺情况产生了以上四种锁,

      无锁:代码块不加锁;

      偏向锁:无竞争、只有一个线程使用锁时,降低轻量级锁产生的性能损耗,(初始化时会进行一次CAS);

      轻量级锁:无竞争,多个线程切换时,不进行用户态和内核态的切换,只需要将synchronize中的mark word中的部分字节CAS更新指向线程栈中的Lock Record,如果更新成功,则轻量级锁获取成功,记录锁状态为轻量级锁,降低重量级锁线程切换、线程阻塞产生的性能开销(每次申请、释放锁时都会进行CAS);

      重量级锁:在轻量级锁尝试加锁时,CAS无法成功时,此时有可能其他线程已经对当前代码块加锁,这时就要进行锁膨胀,将轻量级锁升级为重量级锁;

  自旋锁:为了降低因线程切换造成的性能开销,当前线程如果未获取到锁对象,将进行有限次数n的循环去获取锁对象(如果存在锁竞争但不激烈,仍然可以用自旋锁优化);

================================================================

事务的隔离级别:

  读未提交:会产生脏读,不可重复读,幻读;

  读已提交:会产生不可重复读,幻读,(读的是已提交的版本号);

  可重复读:会产生幻读,(读的是当前版本号之前的、已提交的版本号);

  序列化:整表加锁,性能极低,基本不用。

  MVCC(多版本并发控制):每开启一个事务,版本号就会+1,MVCC采用的是快照读,通过行锁+间隙锁解决幻读问题;

posted @ 2020-08-12 18:07  骑驴晒太阳  阅读(133)  评论(0)    收藏  举报