【java学习—十五】线程的同步与死锁(5)

news2024/11/27 16:37:32

文章目录

  • 1. 多线程产生的问题
  • 2. Synchronized 的使用方法
  • 3. 线程的死锁问题


1. 多线程产生的问题

问题:
同一个账户,支付宝转账,微信转账。两个手机,一个手机开支付宝,另一个手机开微信。假设账户上有3000元,支付宝和微信同时提款2000,这时你的账户余额会变成了-1000元吗?
答:
当然不会,出现就有问题了
    
多个线程执行的不确定性引起执行结果的不稳定
多个线程对账本的共享,会造成操作的不完整性,会破坏数据。

代码实现:

package day15;

public class Test2 {
	public static void main(String[] args) {
		
		//定义账户对象
		Account a = new Account();
		
		//多线程对象
		User u_weixin = new User(a, 2000);
		User u_zhifubao = new User(a, 2000);
		
		Thread weixin = new Thread(u_weixin, "微信");
		Thread zhifubao = new Thread(u_zhifubao, "支付宝");
		
		weixin.start();
		zhifubao.start();
		
	}

}

class Account{
	public static int money = 3000;//全局变量,所有操作共享这个变量
	
	/**
	 * 提款先判断账户钱够不够
	 * 多线程调用这个方法就有问题,线程共享资源时,一个线程在执行这个方法没有完毕时,另一个线程又开始执行这个方法
	 * 解决思路:先让一个线程整体执行完这个方法,另一个线程再执行。
	 * @param m
	 */
	public void drawing(int m) {
		String name = Thread.currentThread().getName();
		
		if(money < m) {
			System.out.println(name + "操作,账户金额不足:" + money);
		}else {
			System.out.println(name + "操作,账户原有金额:" + money);
			System.out.println(name + "操作,取款金额:" + m);
			
			money = money - m;
			
			System.out.println(name + "操作,取款后的余额:" + money);
		}
		
	}
}

class User implements Runnable{
	
	Account account;
	int money;
	
	public User(Account account, int money) {
		this.account = account;
		this.money = money;
	}
	
	@Override
	public void run() {
		account.drawing(money);
		
	}
}

运行结果:

在这里插入图片描述

发现金额变成 -1000 了

    

多线程出现了安全问题

问题的原因
    当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行。导致共享数据的错误。

解决办法 :
    对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。

2. Synchronized 的使用方法

Java 对于多线程的安全问题提供了专业的解决方式:

同步机制

1 、 synchronized 还可以放在方法声明中,表示整个方法为同步方法。
如果针对对象要加同步锁,那就加在方法上,例如:
    public synchronized void show (String name){
        ....
    }

2 、 锁 代码块

如果针对某一段代码需要加同步锁,那就直接在代码块上加同步锁,例如:
    synchronized ( 对象) {
        // 需要被同步的代码;
    }


解决方法:
直接在方法上加上synchronized关键字

package day15;

public class Test2 {
	public static void main(String[] args) {
		
		//定义账户对象
		Account a = new Account();
		
		//多线程对象
		User u_weixin = new User(a, 2000);
		User u_zhifubao = new User(a, 2000);
		
		Thread weixin = new Thread(u_weixin, "微信");
		Thread zhifubao = new Thread(u_zhifubao, "支付宝");
		
		weixin.start();
		zhifubao.start();
		
	}
}

class Account{
	public static int money = 3000;//全局变量,所有操作共享这个变量
	
	/**
	 * 提款先判断账户钱够不够
	 * 多线程调用这个方法就有问题,线程共享资源时,一个线程在执行这个方法没有完毕时,另一个线程又开始执行这个方法
	 * 解决思路:先让一个线程整体执行完这个方法,另一个线程再执行。
	 * 通过 synchronized同步锁 来完成
	 * 可以直接在方法上加上synchronized关键字
	 * 在普通方法上加同步锁synchronized,锁的是整个对象,不是某一个方法
	 * @param m
	 */
	public synchronized void drawing(int m) {
		String name = Thread.currentThread().getName();
		
		if(money < m) {
			System.out.println(name + "操作,账户金额不足:" + money);
		}else {
			System.out.println(name + "操作,账户原有金额:" + money);
			System.out.println(name + "操作,取款金额:" + m);
			
			money = money - m;
			
			System.out.println(name + "操作,取款后的余额:" + money);
		}
	}
		
}

class User implements Runnable{
	
	Account account;
	int money;
	
	public User(Account account, int money) {
		this.account = account;
		this.money = money;
	}
	
	@Override
	public void run() {
		account.drawing(money);
		
	}
}

运行结果:

在这里插入图片描述


在普通方法上加同步锁synchronized,锁的是整个对象,不是某一个方法

举例:

package day15;

public class Test2 {
	public static void main(String[] args) {
		
		//定义账户对象
		Account a = new Account();
		
		//多线程对象
		User u_weixin = new User(a, 2000);
		User u_zhifubao = new User(a, 2000);
		
		Thread weixin = new Thread(u_weixin, "微信");
		Thread zhifubao = new Thread(u_zhifubao, "支付宝");
		
		weixin.start();
		zhifubao.start();
		
		
	}

}

class Account{
	public static int money = 3000;//全局变量,所有操作共享这个变量
	
	/**
	 * 提款先判断账户钱够不够
	 * 多线程调用这个方法就有问题,线程共享资源时,一个线程在执行这个方法没有完毕时,另一个线程又开始执行这个方法
	 * 解决思路:先让一个线程整体执行完这个方法,另一个线程再执行。
	 * 通过 synchronized同步锁 来完成
	 * 可以直接在方法上加上synchronized关键字
	 * 在普通方法上加同步锁synchronized,锁的是整个对象,不是某一个方法
	 * 
	 * 普通方法加同步锁,锁的是当前方法对应的对象,当前的对象的所有加了同步锁的方法是共用一个同步锁
	 * @param m
	 */
	public synchronized void drawing(int m) {
		String name = Thread.currentThread().getName();
		
		if(money < m) {
			System.out.println(name + "操作,账户金额不足:" + money);
		}else {
			System.out.println(name + "操作,账户原有金额:" + money);
			System.out.println(name + "操作,取款金额:" + m);
			
			money = money - m;
			
			System.out.println(name + "操作,取款后的余额:" + money);
		}
		
	}
	
	public synchronized void drawing1(int m) {
		String name = Thread.currentThread().getName();
		
		if(money < m) {
			System.out.println(name + "操作,账户金额不足:" + money);
		}else {
			System.out.println(name + "操作,账户原有金额:" + money);
			System.out.println(name + "操作,取款金额:" + m);
			
			money = money - m;
			
			System.out.println(name + "操作,取款后的余额:" + money);
		}
		
	}
	
	
}

class User implements Runnable{
	
	Account account;
	int money;
	
	public User(Account account, int money) {
		this.account = account;
		this.money = money;
	}
	
	@Override
	public void run() {

		if(Thread.currentThread().getName().equals("微信")) {
			account.drawing(money);
		}else {
			account.drawing1(money);
		}
		
	}
}

运行结果:

在这里插入图片描述

运行结果和上一段相同
说明:锁死的是 Account a 这个对象

普通方法加同步锁,锁的是当前方法对应的对象,当前的对象的所有加了同步锁的方法是共用一个同步锁


不同的对象是不同的锁

举例:

package day15;

public class Test2 {
	public static void main(String[] args) {
		
		//定义账户对象
		Account a = new Account();
		Account a1 = new Account();
		
		//多线程对象
		User u_weixin = new User(a, 2000);
		User u_zhifubao = new User(a1, 2000);
		
		Thread weixin = new Thread(u_weixin, "微信");
		Thread zhifubao = new Thread(u_zhifubao, "支付宝");
		
		weixin.start();
		zhifubao.start();
		
		
	}

}

class Account{
	public static int money = 3000;//全局变量,所有操作共享这个变量
	
	/**
	 * 提款先判断账户钱够不够
	 * 多线程调用这个方法就有问题,线程共享资源时,一个线程在执行这个方法没有完毕时,另一个线程又开始执行这个方法
	 * 解决思路:先让一个线程整体执行完这个方法,另一个线程再执行。
	 * 通过 synchronized同步锁 来完成
	 * 可以直接在方法上加上synchronized关键字
	 * 在普通方法上加同步锁synchronized,锁的是整个对象,不是某一个方法,
	 * 不同的对象是不同的锁,普通方法中加synchronized,线程使用不同的此方法的对象,还是有资源共享的问题
	 * @param m
	 */
	public synchronized void drawing(int m) {
		String name = Thread.currentThread().getName();
		
		if(money < m) {
			System.out.println(name + "操作,账户金额不足:" + money);
		}else {
			System.out.println(name + "操作,账户原有金额:" + money);
			System.out.println(name + "操作,取款金额:" + m);
			
			money = money - m;
			
			System.out.println(name + "操作,取款后的余额:" + money);
		}
		
	}
	
	public synchronized void drawing1(int m) {
		String name = Thread.currentThread().getName();
		
		if(money < m) {
			System.out.println(name + "操作,账户金额不足:" + money);
		}else {
			System.out.println(name + "操作,账户原有金额:" + money);
			System.out.println(name + "操作,取款金额:" + m);
			
			money = money - m;
			
			System.out.println(name + "操作,取款后的余额:" + money);
		}
		
	}
	
	
}

class User implements Runnable{
	
	Account account;
	int money;
	
	public User(Account account, int money) {
		this.account = account;
		this.money = money;
	}
	
	@Override
	public void run() {
	
		if(Thread.currentThread().getName().equals("微信")) {
			account.drawing(money);
		}else {
			account.drawing1(money);
		}
		
	}
}

运行结果:

在这里插入图片描述


如何解决上述问题:

举例:

package day15;

public class Test2 {
	public static void main(String[] args) {
		
		//定义账户对象
		Account a = new Account();
		Account a1 = new Account();
		
		//多线程对象
		User u_weixin = new User(a, 2000);
		User u_zhifubao = new User(a1, 2000);
		
		Thread weixin = new Thread(u_weixin, "微信");
		Thread zhifubao = new Thread(u_zhifubao, "支付宝");
		
		weixin.start();
		zhifubao.start();
		
		
	}

}

class Account{
	public static int money = 3000;//全局变量,所有操作共享这个变量	
	
	/**
	 * 静态方法 + synchronized,对于所有的对象都是使用同一个锁
	 * @param m
	 */
	public static synchronized void drawing2(int m) {
		String name = Thread.currentThread().getName();
		
		if(money < m) {
			System.out.println(name + "操作,账户金额不足:" + money);
		}else {
			System.out.println(name + "操作,账户原有金额:" + money);
			System.out.println(name + "操作,取款金额:" + m);
			
			money = money - m;
			
			System.out.println(name + "操作,取款后的余额:" + money);
		}
		
	}
}

class User implements Runnable{
	
	Account account;
	int money;
	
	public User(Account account, int money) {
		this.account = account;
		this.money = money;
	}
	
	@Override
	public void run() {

		account.drawing2(money);//调用类的静态方法
	}
}

运行结果:

在这里插入图片描述


锁代码块

举例:

package day15;

public class Test2 {
	public static void main(String[] args) {
		
		//定义账户对象
		Account a = new Account();
		Account a1 = new Account();
		
		//多线程对象
		User u_weixin = new User(a, 2000);
		User u_zhifubao = new User(a, 2000);
		
		Thread weixin = new Thread(u_weixin, "微信");
		Thread zhifubao = new Thread(u_zhifubao, "支付宝");
		
		weixin.start();
		zhifubao.start();	
		
	}
}

class Account{
	public static int money = 3000;//全局变量,所有操作共享这个变量
				
	/**
	 * 对代码块加入同步锁
	 * 代码块synchronized(this),所有当前的对象的synchronized(this)同步的代码都是使用同一个锁
	 * @param m
	 */
	public void drawing3(int m) {
		
		synchronized(this) {//表示当前对象的代码块被加了synchronized同步锁
			//用this锁代码块是代表当前的对象,如果在其他的方法中也有synchronized(this)的代码块,使用的都是同一个同步锁
			String name = Thread.currentThread().getName();
			
			if(money < m) {
				System.out.println(name + "操作,账户金额不足:" + money);
			}else {
				System.out.println(name + "操作,账户原有金额:" + money);
				System.out.println(name + "操作,取款金额:" + m);
				
				money = money - m;
				
				System.out.println(name + "操作,取款后的余额:" + money);
			}
		}
	}
	
}

class User implements Runnable{
	
	Account account;
	int money;
	
	public User(Account account, int money) {
		this.account = account;
		this.money = money;
	}
	
	@Override
	public void run() {

		account.drawing3(money);
	}
}

运行结果:

在这里插入图片描述


如果在其他的方法中也有synchronized(this)的代码块,使用的都是同一个同步锁

举例:

package day15;

public class Test2 {
	public static void main(String[] args) {
		
		//定义账户对象
		Account a = new Account();
		
		//多线程对象
		User u_weixin = new User(a, 2000);
		User u_zhifubao = new User(a, 2000);
		
		Thread weixin = new Thread(u_weixin, "微信");
		Thread zhifubao = new Thread(u_zhifubao, "支付宝");
		
		weixin.start();
		zhifubao.start();
	}
}

class Account{
	public static int money = 3000;//全局变量,所有操作共享这个变量
	
	/**
	 * 对代码块加入同步锁
	 * @param m
	 */
	public void drawing3(int m) {
		
		synchronized(this) {//表示当前对象的代码块被加了synchronized同步锁
			//用this锁代码块是代表当前的对象,如果在其他的方法中也有synchronized(this)的代码块,使用的都是同一个同步锁
			String name = Thread.currentThread().getName();
			
			if(money < m) {
				System.out.println(name + "操作,账户金额不足:" + money);
			}else {
				System.out.println(name + "操作,账户原有金额:" + money);
				System.out.println(name + "操作,取款金额:" + m);
				
				money = money - m;
				
				System.out.println(name + "操作,取款后的余额:" + money);
			}
		}
	}
	
	
	public void drawing4(int m) {
		
		synchronized(this) {//表示当前对象的代码块被加了synchronized同步锁
			//用this锁代码块是代表当前的对象,如果在其他的方法中也有synchronized(this)的代码块,使用的都是同一个同步锁
			String name = Thread.currentThread().getName();
			
			if(money < m) {
				System.out.println(name + "操作,账户金额不足:" + money);
			}else {
				System.out.println(name + "操作,账户原有金额:" + money);
				System.out.println(name + "操作,取款金额:" + m);
				
				money = money - m;
				
				System.out.println(name + "操作,取款后的余额:" + money);
			}
		}
	}

}

class User implements Runnable{
	
	Account account;
	int money;
	
	public User(Account account, int money) {
		this.account = account;
		this.money = money;
	}
	
	@Override
	public void run() {

		if(Thread.currentThread().getName().equals("微信")) {
			account.drawing3(money);
		}else {
			account.drawing4(money);
		}
		
		
	}
}

运行结果:

在这里插入图片描述


怎么使用不同的同步锁

举例:
(1)锁同一个对象,设置a、a1两个账户

package day15;

public class Test2 {
	public static void main(String[] args) {
		
		//定义账户对象
		Account a = new Account();
		Account a1 = new Account();
		
		//多线程对象
		User u_weixin = new User(a, 2000);
		User u_zhifubao = new User(a1, 2000);
		
		Thread weixin = new Thread(u_weixin, "微信");
		Thread zhifubao = new Thread(u_zhifubao, "支付宝");
		
		weixin.start();
		zhifubao.start();
		
		
	}

}

class Account{
	public static int money = 3000;//全局变量,所有操作共享这个变量
	
	/**
	 * synchronized修饰代码块,想要根据不同的对象有不同的锁
	 * @param m
	 */
	public void drawing5(int m, Account a) {
		
		synchronized(a) {//表示通过方法的参数传递进来的对象的代码块被加了synchronized同步锁
			//不同的对象就有不同的同步锁
			String name = Thread.currentThread().getName();
			
			if(money < m) {
				System.out.println(name + "操作,账户金额不足:" + money);
			}else {
				System.out.println(name + "操作,账户原有金额:" + money);
				System.out.println(name + "操作,取款金额:" + m);
				
				money = money - m;
				
				System.out.println(name + "操作,取款后的余额:" + money);
			}
		}
	}
	
}

class User implements Runnable{
	
	Account account;
	int money;
	
	public User(Account account, int money) {
		this.account = account;
		this.money = money;
	}
	
	@Override
	public void run() {
		
		account.drawing5(money, account);	
	}
}

运行结果:

在这里插入图片描述


(2)锁同一个对象,只设置a一个账户

package day15;

public class Test2 {
	public static void main(String[] args) {
		
		//定义账户对象
		Account a = new Account();
		
		//多线程对象
		User u_weixin = new User(a, 2000);
		User u_zhifubao = new User(a, 2000);
		
		Thread weixin = new Thread(u_weixin, "微信");
		Thread zhifubao = new Thread(u_zhifubao, "支付宝");
		
		weixin.start();
		zhifubao.start();
		
	}
}

class Account{
	public static int money = 3000;//全局变量,所有操作共享这个变量

	/**
	 * synchronized修饰代码块,想要根据不同的对象有不同的锁
	 * synchronized(a)这个小括号中传入不同的对象就是不同的锁
	 * @param m
	 */
	public void drawing5(int m, Account a) {
		
		synchronized(a) {//表示通过方法的参数传递进来的对象的代码块被加了synchronized同步锁
			//不同的对象就有不同的同步锁
			String name = Thread.currentThread().getName();
			
			if(money < m) {
				System.out.println(name + "操作,账户金额不足:" + money);
			}else {
				System.out.println(name + "操作,账户原有金额:" + money);
				System.out.println(name + "操作,取款金额:" + m);
				
				money = money - m;
				
				System.out.println(name + "操作,取款后的余额:" + money);
			}
		}
	}
	
	
	
}

class User implements Runnable{
	
	Account account;
	int money;
	
	public User(Account account, int money) {
		this.account = account;
		this.money = money;
	}
	
	@Override
	public void run() {
		
		account.drawing5(money, account);
	}
}

运行结果:

在这里插入图片描述

3. 线程的死锁问题

问题情景:
    线程a0,需要执行方法f0
    线程a1,需要执行方法f1
    f0和f1都是有同步锁的方法
    a0调用f1方法并且一直没有执行完f1
    a1调用f0方法并且一直没有执行完f0
    
导致a0和a1线程都在等待对方释放方法,对方都不释放,这样就形成了线程的死锁

死锁
    不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁

解决方法
    ①专门的算法、原则,比如加锁顺序一致
    ②尽量减少同步资源的定义,尽量避免锁未释放的场景

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1216529.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FBI:皇家勒索软件要求350名受害者支付2.75亿美元

导语 最近&#xff0c;FBI和CISA联合发布的一份通告中透露&#xff0c;自2022年9月以来&#xff0c;皇家勒索软件&#xff08;Royal ransomware&#xff09;已经入侵了全球至少350家组织的网络。这次更新的通告还指出&#xff0c;这个勒索软件团伙的赎金要求已经超过了2.75亿美…

CCRC认证是什么?

什么是CCRC认证&#xff1f; 信息安全服务资质&#xff0c;是信息安全服务机构提供安全服务的一种资格&#xff0c;包括法律地位、资源状况、管理水平、技术能力等方面的要求。 信息安全服务资质&#xff08;CCRC&#xff09;是依据国家法律法规、国家标准、行业标准和技术规范…

MCAL实战三(S32K324-NXP EB tresos Port驱动配置详解)

一、前言 PORT驱动初始化就是对微控制器(MCU)的整个PORT模块进行初始化配置。很多端口和管脚被分配有多种不同的功能,即可以进行引脚功能复用,比如通用I/O、模数转换、脉宽调制等功能。因此,对PORT必须有一个整体的配置和初始化,对各管脚的具体配置和使用取决于微控制器和…

嵌套的iframe页面中rem字号变小问题处理

问题原因 如果 html 的 font-size: 100px&#xff0c;那字号为0.16rem的字实际为100px * 0.16 16px 故最外层的html的字号 与iframe下的html字号 不相同时&#xff0c;则会导致iframe页面内的字体字号存在问题 解决办法 先获取外层html的font-size const fontSize par…

熟悉 Unity HDRP设置以提高性能

HDRP Version 10 了解如何利用高清晰度渲染管道(HDRP)设置&#xff0c;以最大限度地提高性能&#xff0c;并一次实现强大的图形。 随着Unity 2020 LTS及以后的HDRP版本10的发布&#xff0c;HDRP包继续优先考虑其用户友好的界面&#xff0c;灵活的功能&#xff0c;稳定性和总体…

锐捷软件开机自启动

http://t.csdnimg.cn/h6k9R win键搜索任务计划程序 打开&#xff0c;在windows创建任务&#xff1a;

【LeetCode刷题-滑动窗口】--424.替换后的最长重复字符

424.替换后的最长重复字符 方法&#xff1a;滑动窗口 右边界先移动找到一个满足题意的可以替换k个字符以后&#xff0c;所有字符都变成一样的当前看来最小的子串&#xff0c;直到右边界纳入一个字符以后&#xff0c;不能满足的时候停下然后考虑左边界右移&#xff0c;左边界只…

使用git上传代码至gitee入门(1)

文章目录 一、gitee注册新建仓库 二、git的下载三、git的简单使用&#xff08;push、pull&#xff09;1、将本地文件推送至gitee初始化配置用户名及邮箱将本地文件提交至gitee补充 2、将远程仓库文件拉取至本地直接拉拉至其他本地文件夹 一、gitee 注册 官网&#xff1a;http…

K8S篇之实现利用Prometheus监控pod的实时数据指标

一、监控部署 1、将k8s集群中kube-state-metrics指标进行收集&#xff0c;服务进行部署 1.1 pod性能指标&#xff08;k8s集群组件自动集成&#xff09; k8s组件本身提供组件自身运行的监控指标以及容器相关的监控指标。通过cAdvisor 是一个开源的分析容器资源使用率和性能特性的…

win11无法打开文件资源管理器

不知道为啥&#xff0c;升级之后文件夹就打不开了&#xff0c;研究了n个方案 注意&#xff1a;先备份一下注册表&#xff0c;祸祸完失败之后恢复回去 最终方案 很悲剧&#xff0c;下面的我都失败了&#xff0c;不过其他人有成功的&#xff0c;所以&#xff0c;我放弃官方的文件…

matlab如何实现任意长序列所有排列方式

最近被问到一个问题&#xff0c;如何计算一个由3个0和3个1组成的序列的所有组合情况&#xff0c;处理这个问题我没有找到特别恰当的函数&#xff08;如果有能直接做的函数欢迎评论告知&#xff09;&#xff0c;所以采用比较接近需求的perms函数来解决这个问题 首先看perms函数…

【人工智能】本地运行开源项目MMSegmentation引发的问题

文章目录 ❌AssertionError: Torch not compiled with CUDA enabled问题描述问题分析解决方案总结参考文献 ❌AssertionError: Torch not compiled with CUDA enabled 问题描述 python demo/image_demo.py demo/demo.png configs/pspnet/pspnet_r50-d8_4xb2-40k_cityscapes-5…

Sonar生成PDF错误Can‘t get Compute Engine task status.Retry..... HTTP error: 401

报错及修改&#xff1a; 报错&#xff1a;INFO: Can’t get Compute Engine task status.Retry… org.sonarqube.ws.connectors.ConnectionException: HTTP error: 401, msg: , query: org.apache.commons.httpclient.methods.GetMethod7a021f49 ERROR: Problem generating PD…

车联网解决方案(车联网设备安装部署案例)

车联网&#xff08;Connected Car&#xff09;是指通过无线通信技术将汽车与互联网连接起来&#xff0c;实现车辆与车辆之间、车辆与道路基础设施之间以及车辆与互联网之间的信息交流和实时控制。车载网关是车联网系统中的核心设备之一&#xff0c;负责将车辆内部的数据传输到云…

java实现钉钉机器人消息推送

项目开发中需要用到钉钉机器人发送任务状态&#xff0c;本来想单独做一个功能就好&#xff0c;但是想着公司用到钉钉机器人发送项目挺多的。所以把这个钉钉机器人抽离成一个组件发布到企业maven仓库&#xff0c;这样可以给其他同事用提高工作效率。 1.目录结构 2.用抽象类&…

分享6个超绝的设计素材网站,绝对好用!

设计师平时都去哪里找素材呢&#xff1f;收藏好这6个网站&#xff0c;绝对能解决你80%的素材需求&#xff0c;话不多说&#xff0c;直接上干货。 设计素材 1、菜鸟图库 https://www.sucai999.com/?vNTYxMjky 菜鸟图库是一个非常大的素材库&#xff0c;站内包含设计、办公、自…

前端常用的几种加密方法

文章目录 前端常用的几种加密方法md5 加密(不可逆)base64 位加密(可加密可解密)RSA 加密(公钥加密&#xff0c;私钥解密)AES 加密(需要密钥才能解密)CryptoJS 常用的加密方式--demo ✒️总结 前端常用的几种加密方法 在信息安全越来越受重视的今天&#xff0c;JS 安全一直是前端…

【文件上传】upload-labs 通关

环境准备 靶场upload-labs-env-win-0.1环境windows 靶场描述 靶场攻略 Pass-01 1.上传一句话木马 发现有类型限制 2.上传图片木马 抓包 3.修改后缀 将png修改为php. 成功上传&#xff0c; 4.查找文件地址 5.中国蚁剑连接 6.成功 7.源码分析 function checkFile() {var fi…

计算机组成原理——第一章

早期冯诺依曼机&#xff1a; 现代计算机&#xff1a; 五大部分&#xff1a; 1. 输入设备&#xff0c;是指将外部信息以计算机能读懂的方式输入进来&#xff0c;如键盘&#xff0c;鼠标等 2.输出设备&#xff0c;就是将计算机处理的信息以人所能接受的方式输出出来&#xff0c;比…

【问题解决】蓝牙显示已配对,无法连接,蓝牙设备显示在其他设备中。

最开始&#xff0c;我发现逻辑鼠标无法连接蓝牙了&#xff0c;怎么都不行&#xff0c;重连&#xff0c;重新配对&#xff0c;全不行。于是尝试用逻辑鼠标内的usb接口进行解决&#xff0c;重连成功。 然而&#xff0c;在连接耳机的时候&#xff0c;发现耳机音频同样无法连接&am…