写在最后
可能有人会问我为什么愿意去花时间帮助大家实现求职梦想,因为我一直坚信时间是可以复制的。我牺牲了自己的大概十个小时写了这片文章,换来的是成千上万的求职者节约几天甚至几周时间浪费在无用的资源上。
上面的这些(算法与数据结构)+(Java多线程学习手册)+(计算机网络顶级教程)等学习资源
一、乐观锁/悲观锁
=========
注意,乐观锁与悲观锁并不是具体的两种锁的实现,而一种设计思想。
乐观锁
===
顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。
乐观锁适用于多读的应用类型,这样可以提高吞吐量,不加锁会带来大量的性能提升,在Java中
java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS(Compare and Swap 比较并交换)实现的。
实现方式
====
数据版本机制
======
实现数据版本一般有两方式,
-
第一种是使用版本号
-
第二种是使用时间戳。
以版本号方式为例。
版本号方式:一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。
update table set xxx=#{xxx}, version=version+1 where id=#{id} and version=#{version};
CAS操作
=====
CAS(Compare and Swap 比较并交换),当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。
CAS操作中包含三个操作数——需要读写的内存位置(V)、进行比较的预期原值(A)和拟写入的新值(B)。如果内存位置V的值与预期原值A相匹配,那么处理器会自动将该位置值更新为新值B,否则处理器不做任何操作。
悲观锁
===
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。比如Java里面的同步原语synchronized关键字的实现就是悲观锁。
悲观锁适合写操作非常多的场景,保证数据的安全。
二、独享锁/共享锁
=========
独享锁是指该锁一次只能被一个线程所持有。
共享锁是指该锁可被多个线程所持有。
ReentrantLock
=============
ReentrantLock是独享锁。但是对于Lock的另一个实现类ReadWriteLock,其读锁是共享锁,其写锁是独享锁。
ReadWriteLock
=============
ReadWriteLock,其读锁是共享锁,其写锁是独享锁。读锁的共享锁可保证并发读是非常高效的,读写,写读,写写的过程是互斥的。
Synchronized
============
Synchronized是独享锁
独享锁与共享锁也是通过AQS来实现的,通过实现不同的方法,来实现独享或者共享。
三、互斥锁/读写锁
=========
上面讲的独享锁/共享锁就是一种广义的说法,互斥锁/读写锁就是具体的实现。
互斥锁在Java中的具体实现就是ReentrantLock。
读写锁在Java中的具体实现就是ReadWriteLock。
四、可重入锁
======
可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。说的有点抽象,下面会有一个代码的示例。
ReetrantLock
============
ReetrantLock从名字就可以看出是一个重入锁,其名字是Re entrant Lock 重新进入锁。
Synchronized
============
对于Synchronized而言,也是一个可重入锁。可重入锁的一个好处是可一定程度避免死锁。
public class AtomicDemo {
// 共享操作的资源 volatile 原子性问题 synchroized Lock AutomicInteger
private static int count = 0 ;
private static Lock lock = new ReentrantLock();
// 定义操作的方法 重入锁
private static void incr(){
try {
lock.lock();// 枷锁
Thread.sleep(1);
count++;
decr();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
最后
一次偶然,从朋友那里得到一份“java高分面试指南”,里面涵盖了25个分类的面试题以及详细的解析:JavaOOP、Java集合/泛型、Java中的IO与NIO、Java反射、Java序列化、Java注解、多线程&并发、JVM、Mysql、Redis、Memcached、MongoDB、Spring、Spring Boot、Spring Cloud、RabbitMQ、Dubbo 、MyBatis 、ZooKeeper 、数据结构、算法、Elasticsearch 、Kafka 、微服务、Linux。
这不,马上就要到招聘季了,很多朋友又开始准备“金三银四”的春招啦,那我想这份“java高分面试指南”应该起到不小的作用,所以今天想给大家分享一下。
请注意:关于这份“java高分面试指南”,每一个方向专题(25个)的题目这里几乎都会列举,在不看答案的情况下,大家可以自行测试一下水平 且由于篇幅原因,这边无法展示所有完整的答案解析
一下水平 且由于篇幅原因,这边无法展示所有完整的答案解析