【面经】京东金融一面凉经

项目

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? 你认为哪个用到索引,哪个没有用到,哪个用全部索引,哪个用部分索引?

 

面试问题解答:

1.你怎么保证你的redis每个线程取商品库存的时候的并发性不会出错? setnx   那setnx怎么用的?后续?redis的setnx锁到了超时时间失效,并发的问题?

SETNX key value

将 key 的值设为 value ,当且仅当 key 不存在。

若给定的 key 已经存在,则 SETNX 不做任何动作。

SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。

可用版本:

>= 1.0.0

时间复杂度:

O(1)

返回值:

设置成功,返回 1 。

设置失败,返回 0 。

 

利用Setnx实现分布式锁,当一个key使用Setnx会隐式的给key加上锁,让其他线程在获取这个key的时候进行阻塞。

具体:

setnx lock.key < currentTime + lockexpiretime+1>  可以加锁,也可以在加锁的同时为锁加上过期时间。

java代码:Jedis 

public class SimpleRedisLock {

    public static ThreadLocal<Jedis> 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方法,删除锁来释放。

常见问题:setnx死锁--出现情况:当一个线程获取锁后, 并在过期时间内崩溃,那么这个线程会一直持有锁,其他线程无法获得锁、

解决方法:不能够简单的获取锁的时间戳,这样会导致多线程竞态,导致多个线程同时获取锁

我们可以通过锁的键对应的时间戳来判断这种情况是否发生了,如果当前的时间已经大于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():GETSET lock.foo <current Unix time + lock timeout + 1> 

GETSET()方法,在获取锁的同时,利用当前时间更新其锁的过期时间。这样若有一个线程检测出c1线程死锁,锁时间过期,那么c2这个线程执行getset()方法后, 获取锁,同时更新锁的过期时间,当下一个线程进来后,发现锁未到期,那么就不会发生锁的争抢。

猜你喜欢

转载自blog.csdn.net/weixin_38035852/article/details/82190885