一 Java中的锁是什么?
/* * 一 Java锁定义? * 在计算机科学中,锁(lock)或互斥(mutex)是一种同步机制,用于在有许多执行线程的环境中强制对资源的访问限制。 * 锁旨在强制实施互斥排他、并发控制策略。 * * 锁的宏观分类? * 乐观锁 和 悲观锁。 * * 二 乐观锁? * 即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为 别人不会修改,所以不会上锁。 版本号机制 和 CAS算法 来实现乐观锁。 但是在更新的时候会判断一下在此期间别人有没有去更新这个数 据,采取在写时 先读出【当前版本号】,然后加锁操作(比较跟上一次的版本号,如果一样则更新), 如果失败则要重复读-比较-写的操作 案例 银行卡 理想型 事物之间不干扰。 事件一 进账 本人银行卡,到月发工资。 此时版本号1 余额 0 , 到账1000, 结束。 整个过程只有新增的一条记录 完成后 版本号 + 1 此时版本号2 事件二 消费 银行卡支付账单,查询余额,此时版本号2 有1000 元 ,扣除消费金额10元 余额 990元 此时版本号3 事件之间互相干扰 事件一和二,同时开始。 版本号都从1开始 让事件一完成,此时的版本号是2 事件二开始,事件二会对版本号进行比较,此时版本号不一致。事件二就会失败。 然后重复读---比较----写的操作。 cas算法? 比较替换。 是一种更新的原子性操作,比较当前的值,和传入的值是否一致性。 一样则更新,否则失败。 CAS利用CPU指令【调用的是本地方法】,从硬件层面保证了操作的原子性, 原语的执行必须是连续的。不存在线程切换的问题。以达到类似于锁的效果。 无锁操作,不可能出现死锁情况。 cas(v,e,n) 想把v 修改成n ,需要v和e 进行比较,二者相同,才跟新变量v,然后把v的值给赋值给新值n。 v 需要更新的变量 e 预期值 n 新值 我们提供一个期望值 e ,当他和v 就是需要更新的变量是相等的。说明还没有线程修改该值。可以执行cas操作。 反之,期望值和需要更新的变量不相等。说明已经被其他线程修改。就不执行更新操作。 可以重新读取该变量,尝试再次修改,也可以放弃操作。 cas bba问题? 对应一个版本号,一个数据一个版本,值相等,版本号相等,才能修改。 三 悲观锁 Synchronized 悲观锁(Pessimistic Lock), 做最坏的打算来处理问题,每次去拿数据的时候都认为别人会修改。 所以每次在拿数据的时候都会上锁。这样别人想拿数据就被挡住,直到悲观锁被释放。 四 区别? 悲观锁阻塞事务,乐观锁回滚重试, 它们各有千秋,取决于实际使用场景。 像乐观锁适用于写比较少的情况下,冲突很少发生的时候,这样可以省去锁的开销,加大了系统的整个吞吐量。 但如果经常产生冲突,上层应用会不断的进行重试,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。 * * * * */