乐观锁和悲观锁的区别
1.悲观锁
1.1悲观锁的概念
悲观锁的代表是synchronized和Lock锁,是相对于乐观锁来说,适合经常发生冲突,即经常发生修改的情况。悲观锁顾名思义,认为会有别的线程来修改我的数据,我需要加锁来保证数据的安全。
1.2悲观锁的思想
- 线程只有获得锁,才能去操作共享变量,每次只有一个线程占锁成功,其他获取锁失败的线程,都得停下来等待。
- 由于当前执行cpu的线程,执行完毕后会释放锁,线程从阻塞状态被notify或notifyAll唤醒来抢夺cpu的执行权,获取锁可以操作共享变量,未占据锁的线程从运行到阻塞,重复上述操作,涉及线程的上下文切换,导致资源的损耗。
- 实际开发中考虑这方面资源的损耗,线程在获得synchronized锁和Lock锁时,如果锁被占用,都会做几次重试操作,减少上下文切换,从而减少资源损耗。
2.乐观锁
2.1乐观锁的概念
乐观锁的代表是AtomicInteger,使用cas来保证原子性。
2.2乐观锁的思想
- 无需加锁,每次只有一个线程能成功修改共享变量,其他失败的线程不需要停止,不断重试直至成功(很乐观,认为通过努力是可以成功的,这也是乐观锁由来的原因之一)。
- 乐观锁的前提是需要多核cpu支持,且线程数不超过cpu数,线程处于运行状态,不需要阻塞,因此不涉及线程上下文切换。
3.总结
通过上述的分析,可以看出二者的区别:
- 悲观锁需要加锁,乐观锁无需加锁
- 悲观锁有阻塞,涉及上下文切换,乐观锁则没有
- 经常出现冲突的情况使用悲观锁,否则推荐使用乐观锁