还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!
王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。
对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!
【完整版领取方式在文末!!】
93道网络安全面试题
内容实在太多,不一一截图了
黑客学习资源推荐
最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
😝朋友们如果有需要的话,可以联系领取~
1️⃣零基础入门
① 学习路线
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
② 路线对应学习视频
同时每个成长路线对应的板块都有配套的视频提供:
2️⃣视频配套工具&国内外网安书籍、文档
① 工具
② 视频
③ 书籍
资源较为敏感,未展示全面,需要的最下面获取
② 简历模板
因篇幅有限,资料较为敏感仅展示部分资料,添加上方即可获取👆
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
3.3、synchronized 和 lock 区别
| 比较 | Lock | synchronized |
| — | — | — |
| 类型 | java接口 | 内置关键字 |
| 开启释放 | 显式锁手动 开启 和 关闭 | 隐式锁
出了作用域自动释放 |
| 代码锁 | 支持 | 支持 |
| 方法锁 | 不支持 | 支持 |
| 锁状态 | 可以判断是否获取到了锁 | 无法判断获取锁的状态 |
| 线程阻塞 | Lock锁就不一定会等待下去 | 线程1(获得锁,阻塞),线程2(等待) |
| 可重入性 | 可重入的,可以判断锁 | 可重入锁,不可以中断的 |
| 公平性 | 默认非公平的(可设置) | 非公平的 |
| 性能 | 性能更好
JVM将花费较少的时间来调度 | 性能一般
JVM将花费较多的时间来调度管理 |
| 扩展性 | 有更好的扩展性(提供更多的子类) | 不支持 |
| 适用场景 | 适合锁大量的同步代码 | 适合锁少量的代码同步问题 |
4、生产者和消费者问题
===========
面试高频:单例模式、八大排序、生产者消费者、死锁
4.1、synchronized实现
wait、notify 必须在 synchronizied 声明的代码中,否则会抛出异常 java.lang.IllegalMonitorStateException
package providerConsumer;
/**
-
@author ajun
-
Date 2021/7/3
-
@version 1.0
-
synchronized版生产者消费者
*/
public class Syn {
public static void main(String[] args) {
Data data = new Data();
//线程1
new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},“A”).start();
//线程2
new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},“B”).start();
//线程3
new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},“C”).start();
//线程4
new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},“D”).start();
}
}
class Data{
private int num;
public int getNum() {
return num;
}
//增加
public synchronized void increment() throws InterruptedException {
//判断等待
//用while,不用if,防止虚假唤醒
while(num!=0){
this.wait();
}
//业务代码
num++;
System.out.println(Thread.currentThread().getName() + " --> " + num);
//通知
this.notifyAll();
}
//减少
public synchronized void decrement() throws InterruptedException {
//判断等待
//用while,不用if,防止虚假唤醒
while(num == 0){
this.wait();
}
//业务代码
num–;
System.out.println(Thread.currentThread().getName() + " --> " + num);
//通知
this.notifyAll();
}
}
- 可能存在的问题
虚假唤醒
在判断等待时,如果用 if ,当线程多的时候,可能会有虚假唤醒
解决办法
if 判断改为 while 判断
因为 if 只会执行一次,执行完会接着向下执行 if()外边的
而 while 不会,直到条件满足才会向下执行 while()外边的
4.2、JUC实现
在JUC中,Lock 替换 synchronized,await 替换 wait,signal 替换 notify。(signal 信号)
package providerConsumer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
-
@author ajun
-
Date 2021/7/3
-
@version 1.0
*/
public class Loc {
public static void main(String[] args) {
Data2 data2 = new Data2();
new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
data2.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},“A”).start();
new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
data2.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},“B”).start();
new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
data2.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},“C”).start();
new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
data2.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},“D”).start();
}
}
class Data2{
private int num = 0;
Lock lock = new ReentrantLock();//定义锁
Condition condition = lock.newCondition();//定义同步监视器
public int getNum() {
return num;
}
//增加
public void increment() throws InterruptedException {
lock.lock();//加锁
try {
//判断等待
while (num != 0){
condition.await();//等待
}
//业务代码
num++;
System.out.println(Thread.currentThread().getName() + " --> " + num);
//通知
condition.signalAll();
} finally {
lock.unlock();//解锁
}
}
//减少
public void decrement() throws InterruptedException {
lock.lock();//加锁
try {
//判断等待
while (num == 0){
condition.await();//等待
}
//业务代码
num–;
System.out.println(Thread.currentThread().getName() + " --> " + num);
//通知
condition.signalAll();
} finally {
lock.unlock();//解锁
}
}
}
Condition实现精准通知唤醒
5、8锁现象
======
8锁就是关于锁的八个现象
① 非静态同步方法的默认锁是 this,静态同步方法的默认锁是 class
② 某一时刻内,只能有一个线程有锁,无论几个方法;前提是用的同一把锁
参考:https://www.cnblogs.com/shamao/p/11045282.html
5.1、2线程 1对象 2方法
两个线程 调用 同一个对象 的 两个同步方法
package lock8;
/**
-
@author ajun
-
Date 2021/7/4
-
@version 1.0
-
两个线程调用同一个对象的两个同步方法
*/
public class Lock1 {
public static void main(String[] args) {
//同一对象
Number number = new Number();
//线程1
new Thread(() -> {number.getOne();},“A”).start();
//线程2
new Thread(() -> {number.getTwo();},“B”).start();
}
}
class Number{
//同步方法1 (非static)
public synchronized void getOne(){
System.out.println(Thread.currentThread().getName() + “: one”);
}
//同步方法2 (非static)
public synchronized void getTwo(){
System.out.println(Thread.currentThread().getName() + “: two”);
}
}
运行结果如下:
A: one
B: two
分析:
被 synchronized 修饰的方法,锁的对象是方法的调用者。因为两个方法的调用者是同一个,所以两个方法用的是同一个锁,先调用方法的先获得锁,先执行
5.2、2线程 1对象 2方法(1sleep)
新增sleep()给某个方法
TimeUnit.SECONDS.sleep(2);
分析:
不管在何处添加休眠后,会中途休眠,但不影响执行顺序。
被synchronized修饰的方法,锁的对象是方法的调用者。因为两个方法的调用者是同一个,所以两个方法用的是同一个锁,先调用方法的先获得锁,先执行,第二个方法只有在第一个方法执行完释放锁之后才执行
5.3、3线程 1对象 3方法(1普通)
新增一个线程调用 同一对象 新增的一个普通方法
分析:
新增的方法没有被 synchronized 修饰,不是同步方法,不受锁的影响,所以不需要等待。其他线程共用了一把锁,所以还需要等待。
5.4、2线程 2对象 2方法(1sleep)
两个线程 调用 两个对象 的同步方法,其中一个方法有sleep()
分析:
被 synchronized 修饰的方法,锁的对象是方法的调用者。因为用了两个对象调用各自的方法,所以两个方法的调用者不是同一个,所以两个方法用的不是同一个锁,后调用的方法不需要等待先调用的方法
5.5、2线程 1对象 2方法(1static)
sleep()的方法设置为static,并且让两个线程用同一个对象调用两个方法
分析:
被synchronized和static修饰的方法,锁的对象是类的class对象。仅仅被synchronized修饰的方法,锁的对象是方法的调用者。因为两个方法锁的对象不是同一个,所以两个方法用的不是同一个锁,后调用的方法不需要等待先调用的方法。
5.6、2线程 1对象 2方法(2sattic)
将两个方法均设置为static方法,并且让两个线程用同一个对象调用两个方法
分析:
被synchronized和static修饰的方法,锁的对象是类的class对象。因为两个同步方法都被static修饰了,所以两个方法用的是同一个锁,后调用的方法需要等待先调用的方法
5.7、2线程 2对象 2方法(1static)
将两个方法中有sleep()的方法设置为static方法,另一个方法去掉static修饰,让两个线程用 两个对象 调用两个方法
分析:
被synchronized和static修饰的方法,锁的对象是类的class对象。仅仅被synchronized修饰的方法,锁的对象是方法的调用者。即便是用同一个对象调用两个方法,锁的对象也不是同一个,所以两个方法用的不是同一个锁,后调用的方法不需要等待先调用的方法。
5.8、2线程 2对象 2方法(2static)
将两个方法均设置为static方法,并且让两个线程用 一个对象 调用两个方法
分析:
被synchronized和static修饰的方法,锁的对象是类的class对象。因为两个同步方法都被static修饰了,即便用了两个不同的对象调用方法,两个方法用的还是同一个锁,后调用的方法需要等待先调用的方法。
5.9、总结
-
普通同步方法
-
一个类里面如果有多个synchronized方法,在使用同一个对象调用的前提下,某一个时刻内,只要一个线程去调用其中的一个synchronized方法了,其他的线程都只能等待,换句话说,某一时刻内,只能有唯一一个线程去访问这些synchronized方法。
-
锁的是当前对象this,被锁定后,其他线程都不能进入到当前对象的其他的synchronized方法。
-
普通方法
-
加个普通方法后发现和同步锁无关
-
静态同步方法
-
换成静态同步方法后,情况又变化
-
所有的非静态同步方法用的都是同一把锁:实例对象本身
-
也就是说如果一个对象的非静态同步方法获取锁后,该对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁,可是其他对象的非静态同步方法因为跟该对象的非静态同步方法用的是不同的锁,所以毋须等待该对象的非静态同步方法释放锁就可以获取他们自己的锁
-
所有的静态同步方法用的也是同一把锁:类对象本身
-
这两把锁是两个不同的对象,所以静态同步方法与非静态同步方法之间不会有竞争条件。但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个对象的静态同步方法,还是其他对象的静态同步方法,只要它们属于同一个类的对象,那么就需要等待当前正在执行的静态同步方法释放锁
| 方法 | 锁的类型 | 等待情况 |
| — | — | — |
| 普通方法 | 没有锁 | 不需要等待 |
| 静态方法 | 没有锁 | 不需要等待 |
| 普通同步方法 | 对象锁 | 同一对象内的多个普通同步方法间需要等待; 不同对象调用时不需要等待 |
| 静态同步方法 | 类锁 | 该类的任何对象调用都需要等待,都是同一把类锁 |
- 只需要判断是否是同一把锁
6、线程安全集合类
=========
1)传统Vector
效率低
还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!
王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。
对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!
【完整版领取方式在文末!!】
93道网络安全面试题
内容实在太多,不一一截图了
黑客学习资源推荐
最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
1️⃣零基础入门
① 学习路线
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
② 路线对应学习视频
同时每个成长路线对应的板块都有配套的视频提供:
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!