学习路线:
这个方向初期比较容易入门一些,掌握一些基本技术,拿起各种现成的工具就可以开黑了。不过,要想从脚本小子变成黑客大神,这个方向越往后,需要学习和掌握的东西就会越来越多以下是网络渗透需要学习的内容:
需要体系化学习资料的朋友,可以加我V获取:vip204888 (备注网络安全)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
public class ThreadDemo {
private int x = 0;
private void count() {
x++;
}
public void runTest() {
new Thread() {
@Override
public void run() {
for (int i = 0; i < 1_000_000; i++) {
count();
}
System.out.println("final x from 1: " + x);
}
}.start();
new Thread() {
@Override
public void run() {
for (int i = 0; i < 1_000_000; i++) {
count();
}
System.out.println("final x from 2: " + x);
}
}.start();
}
public static void main(String[] args) {
new ThreadDemo().runTest();
}
}
示例代码中 runTest 方法2个线程分别执行 1_000_000 次 count() 方法, count() 方法中只执行简单的 x++ 操作,理论上每次执行 runTest 方法应该有一个线程输出的 x 结果应该是2_000_000。但实际的运行结果并非我们所想:
final x from 1: 989840
final x from 2: 1872479
我运行了10次,其中一个线程输出 x 的值为 2_000_000 只出现了2次。
final x from 1: 1000000
final x from 2: 2000000
出现这样的结果的原因也就是我们上面所说的,在多线程环境下,我们主内存的 x 变量的数据被破坏了。我们都知道完成一次 i++ 相当于执行了:
int tmp = x + 1;
x = tmp;
在多线程环境下就会出现在执行完 int tmp = x + 1; 这行代码时就发生了线程切换,当线程再次切回来的时候,x 就会被重复赋值,导致出现上面的运行结果,2个线程都无法输出 2_000_000。
下图描述了示例代码的执行时序:
那么 Java 是如何来解决上述问题来保证线程安全,保证共享内存的原子性、可见性、有序性的呢?
##/ 线程同步 /
Java 提供了一系列的关键字和类来保证线程安全。
Synchronized 关键字
Synchronized 作用
保证方法或代码块操作的原子性
Synchronized 保证⽅法内部或代码块内部资源(数据)的互斥访问。即同⼀时间、由同⼀个 Monitor(监视锁) 监视的代码,最多只能有⼀个线程在访问。
话不多说来张动图描述一下 Monitor 工作机制:
被 Synchronized 关键字描述的方法或代码块在多线程环境下同一时间只能由一个线程进行访问,在持有当前 Monitor 的线程执行完成之前,其他线程想要调用相关方法就必须进行排队,知道持有持有当前 Monitor 的线程执行结束,释放 Monitor ,下一个线程才可获取 Monitor 执行。
如果存在多个 Monitor 的情况时,多个 Monitor 之间是不互斥的。
多个 Monitor 的情况出现在自定义多个锁分别来描述不同的方法或代码块,Synchronized 在描述代码块时可以指定自定义 Monitor ,默认为 this 即当前类。
保证监视资源的可见性
保证多线程环境下对监视资源的数据同步。即任何线程在获取到 Monitor 后的第⼀时 间,会先将共享内存中的数据复制到⾃⼰的缓存中;任何线程在释放 Monitor 的第⼀ 时间,会先将缓存中的数据复制到共享内存中。
保证线程间操作的有序性
Synchronized 的原子性保证了由其描述的方法或代码操作具有有序性,同一时间只能由最多只能有一个线程访问,不会触发 JMM 指令重排机制。
Volatile 关键字
Volatile 作用
保证被 Volatile 关键字描述变量的操作具有可见性和有序性(禁止指令重排)。
注意:
-
Volatile 只对基本类型 (byte、char、short、int、long、float、double、boolean) 的赋值 操作和对象的引⽤赋值操作有效。
-
对于 i++ 此类复合操作, Volatile 无法保证其有序性和原子性。
-
相对 Synchronized 来说 Volatile 更加轻量一些。
java.util.concurrent.atomic
包提供了一系列的 AtomicBoolean、AtomicInteger、AtomicLong 等类。使用这些类来声明变量可以保证对其操作具有原子性来保证线程安全。
实现原理上与 Synchronized 使用 Monitor(监视锁)保证资源在多线程环境下阻塞互斥访问不同,java.util.concurrent.atomic 包下的各原子类基于 CAS(CompareAndSwap) 操作原理实现。
CAS 又称无锁操作,一种乐观锁策略,原理就是多线程环境下各线程访问共享变量不会加锁阻塞排队,线程不会被挂起。通俗来讲就是一直循环对比,如果有访问冲突则重试,直到没有冲突为止。
Lock
Lock 也是 java.util.concurrent 包下的一个接口,定义了一系列的锁操作方法。Lock 接口主要有 ReentrantLock,ReentrantReadWriteLock.ReadLock,ReentrantReadWriteLock.WriteLock 实现类。与 Synchronized 不同是 Lock 提供了获取锁和释放锁等相关接口,使得使用上更加灵活,同时也可以做更加复杂的操作,如:
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
Lock readLock = lock.readLock();
Lock writeLock = lock.writeLock();
private int x = 0;
private void count() {
writeLock.lock();
try {
x++;
} finally {
writeLock.unlock();
}
}
private void print(int time) {
readLock.lock();
try {
for (int i = 0; i < time; i++) {
System.out.print(x + " ");
}
System.out.println();
} finally {
还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!
王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。
对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!
【完整版领取方式在文末!!】
93道网络安全面试题
需要体系化学习资料的朋友,可以加我V获取:vip204888 (备注网络安全)
内容实在太多,不一一截图了
黑客学习资源推荐
最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
😝朋友们如果有需要的话,可以联系领取~
1️⃣零基础入门
① 学习路线
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
② 路线对应学习视频
同时每个成长路线对应的板块都有配套的视频提供:
2️⃣视频配套工具&国内外网安书籍、文档
① 工具
② 视频
③ 书籍
资源较为敏感,未展示全面,需要的最下面获取
② 简历模板
因篇幅有限,资料较为敏感仅展示部分资料,添加上方即可获取👆
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!