java基础——多线程——锁
锁:synchronized和Lock
- synchronized:是托管给jvm运行的,如果锁定的代码块出现异常,synchronized会自动释放锁,不会因为出现异常没有释放锁而出现死锁,
- Lock:是java写的控制锁的代码,所以没有jvm带来的自动的功能,出现异常时必须手动的在finally块释放锁,否则将会引起死锁。
- 总结:如果锁的竞争不是很激烈的话,偶尔有同步的情况下,使用synchronized是最好的。
乐观锁和悲观锁
- 乐观锁:总是认为不会发生并发的问题,读取数据时不会认为有其他线程对数据的改变,因此不会上锁,但更新数据时会判断在这之前有没有其它线程对数据更改,一般会采用版本号version字段或CAS操作
version字段方法:就是在数据表中添加一个为version的字段,其字段在每次修改数据时都会加一。在读取值得时候会读取到version的值,在提交更新时,若刚才读取到的version值等于当前数据库的version值时才更新,否则重新更新操作,直到更新成功。
CAS法:在更新时,当前的内存值更之前取到的内存值一样时才会赋上新值,否则重试更新操作,直到更新成功。
- 悲观锁:总是假设最坏的情况,每次取数据时都会认为其它线程会修改,所以都会上锁(读锁、写锁、行锁),可以依靠数据库实现,在操作之前加锁,其它线程访问时都会堵塞挂起。类似于java中的synchronized。
分布式锁
- 三种实现的方式:
1. 基于数据库实现的分布式锁
2. 基于缓存(Redis、memcached、tair)实现的
3. 基于Zookeeper实现分布式锁