//模拟售票类
public class Ticket implements Runnable{
int T = 100; //定义100张票
@Override
public void run() {
while (true)
{
try {
Thread.sleep(10); //加了休眠,让其他线程有机会执行
} catch (InterruptedException e) {
e.printStackTrace();
}
if(T > 0)
{
System.out.println(Thread.currentThread().getName() + T–);
}
}
}
}
public static void main(String[] args)
{
//创建Runnable接口类实现对象
Ticket t = new Ticket();
//创建三个Thread对象,传递Runnable类实现对象
Thread T1 = new Thread(t,“窗口1:”);
Thread T2 = new Thread(t,“窗口2:”);
Thread T3 = new Thread(t,“窗口3:”);
//开启线程
T1.start();
T2.start();
T3.start();
}
-
当我们运行代码时,会发现出现了重复的票,这和我们预期的结果不一样,这就出现了多线程安全问题
-
多线程安全问题都是由全局变量及静态变量引起的,若每个线程中对全局变量、静态变量只有读操作没有写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,就可能有线程安全问题,一般采用线程同步来解决这个问题
-
在Java中抢占式调度,当程序在售票类运行的时候,进入run方法的while循环里的if循环的时候,可能没有抢到CPU而发生阻塞,并且这三个线程都有可能阻塞在这个位置,所以会出现打印出负数的情况
二、线程同步
======
Java中提供了线程同步机制,有效的解决了线程安全问题,线程同步有以下两种方式:
-
方法一:同步代码块
-
方法二:同步方法
1、同步代码块
格式:在代码块声明上,加上 synchronized
_synchronized (锁对象) {
可能会产生线程安全问题的代码块
}_
注:同步代码块中的锁对象可以是任意对象,但多个线程时,要使用同一个锁对象才能够保证线程安全
对售票的案例进行改进:
public class Ticket implements Runnable{
int T = 10;
//定义锁对象
Object lock = new Object();
@Override
public void run() {
while (true)
{
//同步代码块
synchronized (lock)
{
if(T > 0)
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + T–);
}
}
}
}
}
对上述代码进行改进,增加了同步代码块,即同步锁,当线程进入同步代码块的时候,会判断有没有同步锁,如果有,则获取同步锁,进入同步中,去执行代码块,执行完毕后,出去了同步代码块,线程就将锁还回去,如果判断没有锁,就被阻挡在同步代码块外面不能执行,只能等待,这样,线程安全问题就解决了,但导致程序运行的速度下降了。总:没有锁的线程不能进入同步,在同步中的线程,不出去同步,就不会释放锁。
2、同步方法
(1) 普通方法同步
格式:在方法声明上加上 synchronized
_public synchronized void method() {
可能会产生线程安全问题的代码
}_
注:同步方法中的锁对象是 this
再对售票的案例进行改进:
public class Ticket implements Runnable{
int T = 10;
//定义锁对象
Object lock = new Object();
@Override
public void run() {
while (true)
{
//同步方法
method();
}
}
private synchronized void method()
{
if(T > 0)
{
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + T–);
}
}
}
同步方法也能解决线程安全问题
(2) 静态同步方法
格式:在方法声明上加上 static synchronized
_public static synchronized void method(){
可能会产生线程安全的代码
}_
注:静态同步方法中的锁对象是 类名.class
三、死锁
====
在使用同步锁的时候,存在弊端:当线程任务中出现多个同步(多个锁)时,如果同步中嵌套了其他的同步。这时容易引发程序的无限等到,这种现象称为死锁。
格式:
_synchronized(A锁){
synchronized(B锁){
}
}_
四、Lock 接口
=========
Lock 接口实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作,Lock 接口中常用方法如下:
-
void lock():获得锁
-
void unlock():释放锁
使用 Lock 接口继续对售票案例进行修改:
public class Ticket implements Runnable{
int T = 10;
//创建Lock对象
Lock ck = new ReentrantLock();
@Override
public void run() {
while (true)
{
//调用lock方法获取锁
ck.lock();
if(T > 0)
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + T–);
}
//释放锁
ck.unlock();
}
}
}
五、等待和唤醒机制
=========
等待唤醒机制是为了方便处理进程之间通信的手段,多个线程在处理同一个资源时,由于处理的动作(线程的任务)不行同,为了使各个线程能够有效的利用资源,便采取了等待唤醒机制。等待唤醒机制涉及到的方法:
-
wait():等待。将正在执行的线程释放其执行资格和执行权,并存储到线程池中
-
notify():唤醒。唤醒线程池中被 wait() 的线程,一次唤醒一个,而且是任意的
-
notifyAll():唤醒全部。可以将线程池中的所有 wati() 线程都唤醒
注:
-
这些方法都是在同步中才有效,在使用时必须注明所属锁,这样才可以明确出这些方法操作的到底是哪个锁上的线程
-
因为这些方法在使用的时候要注明所属的锁,而锁又是任意对象,所以这些方法是定义在 Object 类中的
代码实例:
来看一个例子,现有Person类,存储了姓名和年龄,使用 inPut 线程对 Person 类输入信息,使用 outPut 线程对 Person 类获取打印信息
//模拟Person类
public class Person {
String name;
int age;
boolean flag = false;
}
//输入线程任务inPut类
public class inPut implements Runnable {
private Person p;
int count = 0;
public inPut(Person p) {
this.p = p;
}
public void run() {
while (true)
{
synchronized §
{
本人从事网路安全工作12年,曾在2个大厂工作过,安全服务、售后服务、售前、攻防比赛、安全讲师、销售经理等职位都做过,对这个行业了解比较全面。
最近遍览了各种网络安全类的文章,内容参差不齐,其中不伐有大佬倾力教学,也有各种不良机构浑水摸鱼,在收到几条私信,发现大家对一套完整的系统的网络安全从学习路线到学习资料,甚至是工具有着不小的需求。
最后,我将这部分内容融会贯通成了一套282G的网络安全资料包,所有类目条理清晰,知识点层层递进,需要的小伙伴可以点击下方小卡片领取哦!下面就开始进入正题,如何从一个萌新一步一步进入网络安全行业。
学习路线图
其中最为瞩目也是最为基础的就是网络安全学习路线图,这里我给大家分享一份打磨了3个月,已经更新到4.0版本的网络安全学习路线图。
相比起繁琐的文字,还是生动的视频教程更加适合零基础的同学们学习,这里也是整理了一份与上述学习路线一一对应的网络安全视频教程。
网络安全工具箱
当然,当你入门之后,仅仅是视频教程已经不能满足你的需求了,你肯定需要学习各种工具的使用以及大量的实战项目,这里也分享一份我自己整理的网络安全入门工具以及使用教程和实战。
项目实战
最后就是项目实战,这里带来的是SRC资料&HW资料,毕竟实战是检验真理的唯一标准嘛~
面试题
归根结底,我们的最终目的都是为了就业,所以这份结合了多位朋友的亲身经验打磨的面试题合集你绝对不能错过!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!