项目
1.你讲一下你的秒杀项目?
2.秒杀最重要的点在哪?你说一下
3.你怎么保证你的redis每个线程取商品库存的时候的并发性不会出错? setnx 那setnx怎么用的?后续?redis的setnx锁到了超时时间失效,并发的问题
框架
1.看你用过springboot,了解springcloud吗? 不了解 微服务?
2.RPC框架了解过吗?这个最进挺火的? https://www.cnblogs.com/huangqingshi/p/7803642.html
java基础
1.锁synchronized ReentrantLock
2.并发包下的ConcurrentHashMap实现原理,以及内部数据结构 segment是什么结构?
3.并发包下 AtomicInteger利用什么实现?说一下CAS+volatile
3.HashMap的扩容resize()方法,讲一下
4.让你设计一个如何让一个对象转化为json串? --提示,利用反射 fastjson的实现?
5.ThreadLocal你觉得是解决什么样场景下的问题的? 线程私有数据,数据隔离------那么ThreadLocal的key是怎么存储的?怎么保证是线程之间不冲突的????
计算机网络
1.http中get 和post的区别?--面试官认为get不安全不是get的问题,是http本身的原因?不是很懂什么意思
2.一致性哈希?什么是一致性哈希? https://www.cnblogs.com/color-my-life/p/5799903.html 这个文章讲的比较透彻
操作系统
1.一句话说明进程和线程的区别???
2.进程之间的通信方式
Linux
1.查询进程的命令。。。说了半天ps 后面加什么,没明白,用的也不多
2.查看文件的命令
数据库
1.数据库的隔离级别,InnoDB的默认的使用的隔离界别
2.jdbc 如何操作? jdbc的事务如何操作
3.索引,联合索引的访问?如果用A,B,C同时创建索引,查询的时候是 select A andB? A and C? B and C? 你认为哪个用到索引,哪个没有用到,哪个用全部索引,哪个用部分索引?
SETNX key value
将 key
的值设为 value
,当且仅当 key
不存在。
若给定的 key
已经存在,则 SETNX 不做任何动作。
SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。
可用版本:
>= 1.0.0
时间复杂度:
O(1)
返回值:
设置成功,返回 1
。
设置失败,返回 0
。
具体:
setnx lock.key < currentTime + lockexpiretime+1> 可以加锁,也可以在加锁的同时为锁加上过期时间。
java代码:Jedis
public class SimpleRedisLock {
public static ThreadLocal holder = new ThreadLocal<>();
public static JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "localhost");
public static void acquire(String lock){
Jedis jedis = jedisPool.getResource();
while(jedis.setnx(lock, "") == 0){ //上锁并设置过期时间
System.out.println(Thread.currentThread().getName()+"我卡在了jedis.setnx(lock,");
} //set and if not exist 设置key并判断是否存在
holder.set(jedis);
}
public static void release(String lock){
Jedis jedis = holder.get();
jedis.del(lock);
jedis.close();
}
}
key的上锁与释放,在获取该key并对其操作的时候,先用acquire()方法判断是否能够获取锁,若能够获取锁(返回值1),那么执行业务操作,若拿不到(返回值0),那么等待。
当操作完了,通过redis中del方法,删除锁来释放。
解决方法:不能够简单的获取锁的时间戳,这样会导致多线程竞态,导致多个线程同时获取锁
我们可以通过锁的键对应的时间戳来判断这种情况是否发生了,如果当前的时间已经大于lock.foo的值,说明该锁已失效,可以被重新使用。
发生这种情况时,可不能简单的通过DEL来删除锁,然后再SETNX一次,当多个客户端检测到锁超时后都会尝试去释放它,这里就可能出现一个竞态条件,让我们模拟一下这个场景:
C0操作超时了,但它还持有着锁,C1和C2读取lock.foo检查时间戳,先后发现超时了。
C1 发送DEL lock.foo
C1 发送SETNX lock.foo 并且成功了。
C2 发送DEL lock.foo
C2 发送SETNX lock.foo 并且成功了。
这样一来,C1,C2都拿到了锁!问题大了!
GETSET()方法,在获取锁的同时,利用当前时间更新其锁的过期时间。这样若有一个线程检测出c1线程死锁,锁时间过期,那么c2这个线程执行getset()方法后, 获取锁,同时更新锁的过期时间,当下一个线程进来后,发现锁未到期,那么就不会发生锁的争抢。