文章目录
蔚来–提前批
SpringAOP自调用的原因
一般在Spring的生命周期中,开始扫描bean的时候会注册bean ,以及初始化的时候会docCreateBean(针对单例bean),此时BeanPostProcessor的postProcessAfterInitialization回去进行动态代理的处理的动作—创建返回的是一个动态代理对象,容器中存放的也是代理对象。
总结来说,这个this不是容器中得到的代理对象(原因:methodB方法的调用拿到的不是代理对象,此时访问这个非代理对象的methodA,就是类的methodA方法-----而不是代理对象的methodA)
解决的方法(想办法拿到代理对象)
Redisson分布式信号量的实现原理
一般调用接口创建一个分布式信号量的时候,本质是创建一个异步的命令执行器,用于执行redis相关的命令(Lua脚本命令)
java中的Semaphore分布式信号量
Sync重写的释放是比较常规的公共的方法
Sync的state等成员变量,还是利用的父类AQS的成员变量模板的形式(State属于volatile的可见的变量)
分布式信号量同样也分为公平模式与非公平的模式,相应的继承一个非公平(直接使用父类的非公平的TryAcquire—直接CAS尝试抢锁)和公平(重写相应的TryAcquiredShared得方法,需要先判断同步队列中是否存在其他的等待节点。)的Sync的同步器
AQS的基本原理概述
注意Reentranlock的state初始化为0,一旦占锁就会加1,如果是自己可重入还会继续加1,注意释放锁也需要一层一层减1为0
ReentranLock和AQS
ReentranLock使用了AQS的同步器实现,相应的tryAcquire和TryRelease的实现State状态的修改;同时实现Lock接口之外,该类还定义了许多public和protected的方法来检查锁的状态。
Reentranlock首先定义最原始的同步对象,接着针对公平与非公平进行继承进一步拓展重写相关的逻辑
针对公平锁与非公平锁的同步器进行继承Sync进一步拓展重写相关的逻辑
公平锁与非公平锁主要是针对Sync同步器中的相关初始化CAS抢锁的过程重写+AQS中的acquire中的tryAcquire()方法重写(用于lock方法中)
Reentranlock调取lock方法的真实的逻辑,按照是公平锁与非公平锁相应的重写覆盖相应的原始的框架的方法(3部曲:2次CAS(initialTryLock+tryAcquire())+1次Acquire进入阻塞队列)
自定义同步工具的框架
Mylock类实现lock接口,主要是规范的使用lock方法和tryLock方法(本质调用同步的方法) && 之后实现相应的自己内部的同步器(state,tryAcquire和tryRelease的方法)。
在自己的lock类内部,主要是实现自己的同步器,主要是实现一个继承AbstractQueuedSynchronizer类完成同步器的相关方法要么是独占方法,要么是共享方法,他们也只需实现tryAcquire-tryRelease、tryAcquireShared-tryReleaseShared中的一种即可。
也可以实现继承lock接口,要不然就自己定义lock和unLock的方法,在里面调用重写的Acquire与release的方法。
多线程并发引发的问题
非法数据是针对共享资源的状态而言的(同一个线程上下文切换之间,不知道有别的线程进入了,此时应该需要做的是使用synchronized或者别的线程间的通信方式锁住某段代码,防止在线程执行期间尝试改变原始的共享资源的状态值-----这边的讨论是从主存中获取最新的值)
假设同时开启了三个窗口的线程进行卖票操作
再拿这种实现的不安全的单例对象说事,现在就能明白了!!!
下面使用synchronized锁住了临界区的代码的执行,这样不会出现线程的安全问题!!!
秒杀的高并发的问题有哪些
Bitmap底层的实现原理
键与bitmap数组的位置映射关系
将键各个定位一个bit数组相关的位置并置该位置为1,之后利用工具统计相应的整个数组的1的总数(注意可能需要新加入的key对应的offset大于了原始的数组的长度,此时需要对数组进行扩容)
牛客网的项目的键就是用户的id,直接id就是相应的偏移量
根据bitmap的key(比如字符串的形式)如何定位在这个bit数组的位置呢??(可以使用hash算法,或者使用多层的hash算法解决hash碰撞)
这个总结的很好
如何统计redis中bitcount数组中的1的个数(查表法+SWAR算法)
查表法(使用少量位数的情况):
SWAR算法(针对32位–4字节的情况进行判断):
知乎大神讲解,有空看一下
跑了一下
redis的统计维数组的bit个数采用的是查表法(不足28字节,每个字节按照查表法,即8比特共256种可能)和SWAR算法(每4个字节进行处理–共读取7组)相结合的方法
long long redisPopcount(void *s, long count) {
long long bits = 0;
unsigned char *p = s;
uint32_t *p4;
// 为查表法准备的表
static const unsigned char bitsinbyte[256] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};
// CPU一次性读取8个字节,如果4字节跨了两个8字节,需要读取两次才行
// 所以考虑4字节对齐,只需读取一次就可以读取完毕
while((unsigned long)p & 3 && count) {
bits += bitsinbyte[*p++];
count--;
}
// 一次性处理28字节,单独看一个aux就容易理解了,其实就是SWAR算法
// uint32_t:4字节
p4 = (uint32_t*)p;
while(count>=28) {
uint32_t aux1, aux2, aux3, aux4, aux5, aux6, aux7;
aux1 = *p4++;// 一次性读取4字节
aux2 = *p4++;
aux3 = *p4++;
aux4 = *p4++;
aux5 = *p4++;
aux6 = *p4++;
aux7 = *p4++;
count -= 28;// 共处理了4*7=28个字节,所以count需要减去28
aux1 = aux1 - ((aux1 >> 1) & 0x55555555);
aux1 = (aux1 & 0x33333333) + ((aux1 >> 2) & 0x33333333);
aux2 = aux2 - ((aux2 >> 1) & 0x55555555);
aux2 = (aux2 & 0x33333333) + ((aux2 >> 2) & 0x33333333);
aux3 = aux3 - ((aux3 >> 1) & 0x55555555);
aux3 = (aux3 & 0x33333333) + ((aux3 >> 2) & 0x33333333);
aux4 = aux4 - ((aux4 >> 1) & 0x55555555);
aux4 = (aux4 & 0x33333333) + ((aux4 >> 2) & 0x33333333);
aux5 = aux5 - ((aux5 >> 1) & 0x55555555);
aux5 = (aux5 & 0x33333333) + ((aux5 >> 2) & 0x33333333);
aux6 = aux6 - ((aux6 >> 1) & 0x55555555);
aux6 = (aux6 & 0x33333333) + ((aux6 >> 2) & 0x33333333);
aux7 = aux7 - ((aux7 >> 1) & 0x55555555);
aux7 = (aux7 & 0x33333333) + ((aux7 >> 2) & 0x33333333);
bits += ((((aux1 + (aux1 >> 4)) & 0x0F0F0F0F) +
((aux2 + (aux2 >> 4)) & 0x0F0F0F0F) +
((aux3 + (aux3 >> 4)) & 0x0F0F0F0F) +
((aux4 + (aux4 >> 4)) & 0x0F0F0F0F) +
((aux5 + (aux5 >> 4)) & 0x0F0F0F0F) +
((aux6 + (aux6 >> 4)) & 0x0F0F0F0F) +
((aux7 + (aux7 >> 4)) & 0x0F0F0F0F))* 0x01010101) >> 24;
}
/* 剩余的不足28字节,使用查表法统计 */
p = (unsigned char*)p4;
while(count--) bits += bitsinbyte[*p++];
return bits;
}