一、网安学习成长路线图
网安所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
二、网安视频合集
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
三、精品网安学习书籍
当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。
四、网络安全源码合集+工具包
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
五、网络安全面试题
最后就是大家最关心的网络安全面试题板块
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
public class ThreadSafeTest {
public static Map<Integer,Integer> map=new ConcurrentHashMap<>();
public static void main(String[] args) {
ExecutorService pool1 = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
pool1.execute(new Runnable() {
@Override
public void run() {
Random random=new Random();
int randomNum=random.nextInt(10);
if(map.containsKey(randomNum)){
map.put(randomNum,map.get(randomNum)+1);
}else{
map.put(randomNum,1);
}
}
});
}
}
}
这段代码是用10个线程测试10以内各个整型随机数出现的次数,表面上看采用ConcurrentHashMap进行contain和put操作没有任何问题。但是仔细想下,尽管 containsKey和 put 两个方法都是原子的,但在jvm中并不是将这段代码做为单条指令来执行的,例如:假设连续生成2个随机数1,map的 containsKey 和 put 方法由线程A和B 同时执行 ,那么有可能会出现A线程还没有把 1 put进去时,B线程已经在进行if 的条件判断了,也就是如下的执行顺序:
A: map 正在放置随机数 1 进去
A 被挂起
B: 执行 map.containsKey(1) 返回false
B: 将随机数 1 放进 map
A: 将随机数 1 放进 map
map 中key 为1 的value值 还是为 1
这样会导致虽然生成了2次随机数 1 ,它的value值还是1,我们期望的结果应该是2,这并不是我们想要的结果。概括的说就是两个线程同时竞争map, 但他们对map访问顺序必须是先 containsKey 然后再 put 对象进去,即产生了竞态条件。解决方法当然就是同步了,现在我们将代码改成如下:
public class ThreadSafeTest {
public static Map<Integer,Integer> map=new ConcurrentHashMap<>();
public static void main(String[] args) {
ExecutorService pool1 = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
pool1.execute(new Runnable() {
@Override
public void run() {
Random random=new Random();
int randomNum=random.nextInt(10);
countRandom(randomNum);
}
});
}
}
public static synchronized void countRandom(int randomNum){
if(map.containsKey(randomNum)){
map.put(randomNum,map.get(randomNum)+1);
}else{
map.put(randomNum,1);
}
}
}
上述代码在当前类中没有线程安全的问题,但依然有线程安全的危险,成员变量map依然有可能会在其他地方被更改,在java并发中属于无效的同步锁,将countRandom修改成如下即可:
public static void countRandom(int randomNum){
synchronized(map){
if(map.containsKey(randomNum)){
map.put(randomNum,map.get(randomNum)+1);
}else{
map.put(randomNum,1);
}
}
}
在上述代码中由于同步的原因,ConcurrentHashMap 即使换成HashMap 也可以,只要保证map的各个操作都是线程安全的即可。
写这篇文章也是我工作中经历的一个bug, 我目前是在从事酒店行业的房间预订工作,由于每一个房型会有多个不同的产品进行售卖,在通过接口获取数据时,需要将名称相同的房型合并成为一个产品进行展示售卖,例如以下数据:
{
“roomId”: 1,
“roomName”: “大床房”,
“price”: 1805
}, {
“roomId”: 2,
“roomName”: “大床房”,
“price”: 1705
}, {
“roomId”: 3,
“roomName”: “大床房”,
“price”: 1605
}
由于是面向C端用户需要实时展示各个房型产品的价格,所以采用了多线程并使用 ConcurrentHashMap ,其中key为房型名称roomName,value为3个房型产品的数据,所以我就在线程内部使用了如下代码:
if(map.containsKey(roomName)){
map.put(roomName, map.get(roomName)+roomData2);
}else{
map.put(roomName,roomData);
}
由于公司代码不便贴出来,用以上代码展示。逻辑就是若map中包含名称相同的产品则将其取出来放到一个 List中再 put 进去。结果就是当数据量大的时候,大床房的部分价格会被覆盖没有展示出来,导致我们的产品体验很差。最后的解决办法就是上面的采用 synchronized 关键字对map做同步,这样大床房的每一个价格都会展示出来,bug解决。
2019-04-02 更新
评论区中有人提到 可以使用 ConcurrentHashMap 的 putIfAbsent 方法 ,我们看下这个方法:
public V putIfAbsent(K key, V value) {
return putVal(key, value, true);
}
/** Implementation for put and putIfAbsent */
final V putVal(K key, V value, boolean onlyIfAbsent) {
if (key == null || value == null) throw new NullPointerException();
int hash = spread(key.hashCode());
int binCount = 0;
for (Node<K,V>[] tab = table;😉 {
Node<K,V> f; int n, i, fh;
if (tab == null || (n = tab.length) == 0)
tab = initTable();
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
if (casTabAt(tab, i, null,
new Node<K,V>(hash, key, value, null)))
break; // no lock when adding to empty bin
}
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
else {
V oldVal = null;
synchronized (f) {
if (tabAt(tab, i) == f) {
if (fh >= 0) {
binCount = 1;
for (Node<K,V> e = f;; ++binCount) {
K ek;
if (e.hash == hash &&
((ek = e.key) == key ||
(ek != null && key.equals(ek)))) {
oldVal = e.val;
if (!onlyIfAbsent)
e.val = value;
break;
}
Node<K,V> pred = e;
给大家的福利
零基础入门
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
同时每个成长路线对应的板块都有配套的视频提供:
因篇幅有限,仅展示部分资料
网络安全面试题
绿盟护网行动
还有大家最喜欢的黑客技术
网络安全源码合集+工具包
所有资料共282G,朋友们如果有需要全套《网络安全入门+黑客进阶学习资源包》,可以扫描下方二维码领取(如遇扫码问题,可以在评论区留言领取哦)~
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!