package day15;
/**
* @五种情况下添加synchronized的功能体现
* @Author 代码晓菜鸡
* @Date 2021/3/15
*/
/**
* 普通方法加同步锁,锁的是当前方法对应的new对象,当前对象的所有加了同步锁的方法是共用一个同步锁
* public synchronized void drawing1(int m){}
* 另外:若方法上加了static则对类加锁
*
* 代码块类似synchronized (this)的都是使用同一个同步锁
* public void drawing3(int m) {
* synchronized (this){}
*
* 代码块类似synchronized (account)的使用不同的同步锁
* public void drawing3(int m, Account account) {
* synchronized (account){}
*/
/**
* 应用场景:微信支付宝同时对同一账户进行取款操作(drawing),需要保证线程安全
*/
public class Test2 {
public static void main(String[] args) {
//定义账户对象
Account account = new Account();
// Account account1 = new Account();
//定义多线程对象
User user_weixin = new User(account, 2000);
User user_zhifubao = new User(account, 2000);
Thread weixin = new Thread(user_weixin, "微信");
Thread zhifubao = new Thread(user_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);
System.out.println(name + "操作,取款操作:原金额" + money + " - 取款金额" + m);
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);
System.out.println(name + "操作,取款操作:原金额" + money + " - 取款金额" + m);
money -= m;
System.out.println(name + "操作,账户现有余额:" + money);
}
}
/**
* 静态方法加上同步锁,对于所有new对象都是同一个锁
*
* @param m
*/
public synchronized static 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);
System.out.println(name + "操作,取款操作:原金额" + money + " - 取款金额" + m);
money -= m;
System.out.println(name + "操作,账户现有余额:" + money);
}
}
/**
* 对代码块加入同步锁
* @param m
*/
public void drawing3(int m) {
synchronized (this){//表示当前对象的代码块加入同步锁
//用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);
System.out.println(name + "操作,取款操作:原金额" + money + " - 取款金额" + m);
money -= m;
System.out.println(name + "操作,账户现有余额:" + money);
}
}
}
public void drawing4(int m) {
synchronized (this){//表示当前对象的代码块加入同步锁
//用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);
System.out.println(name + "操作,取款操作:原金额" + money + " - 取款金额" + m);
money -= m;
System.out.println(name + "操作,账户现有余额:" + money);
}
}
}
/**
* synchronized修饰代码块,想要根据不同的对象有不同的锁
* synchronized()的括号中加入不同的同步锁
* wait() notify() notifyAll()只能放在有同步锁的方法或代码块中
* @param m
*/
public void drawing5(int m, Account account) {
synchronized (account){//表示当前方法的参数传递进来的代码的对象块加入同步锁
//不停的对象就有不同的同步锁
String name = Thread.currentThread().getName();
//如果微信操作,先不执行,等待支付宝操作,支付宝操作完毕微信继续
if (Thread.currentThread().getName().equals("微信")){
try {
account.wait();//如果当前线程进入等待阻塞状态
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (money < m) {
System.out.println(name + "操作,余额不足:" + money);
} else {
System.out.println(name + "操作,账户原有金额:" + money);
System.out.println(name + "操作,账户取款金额:" + m);
System.out.println(name + "操作,取款操作:原金额" + money + " - 取款金额" + m);
money -= m;
System.out.println(name + "操作,账户现有余额:" + money);
}
if (Thread.currentThread().getName().equals("支付宝")){
try {
// account.notify();//唤醒当前优先级高的线程,进入就绪状态
account.notifyAll();//唤醒当前所有的线程,进入就绪状态
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
class User implements Runnable {
int money;
Account account;
public User(Account account, int money) {
this.money = money;
this.account = account;
}
@Override
public void run() {
/**
* 同种情况同时解除行注释
*/
// account.drawing(money);//情况1
if (Thread.currentThread().getName().equals("微信")){//情况2、3
// account.drawing(money);//情况3
account.drawing3(money);//情况2
}else if (Thread.currentThread().getName().equals("支付宝")){//情况2、3
// account.drawing1(money);//情况3
account.drawing4(money);//情况2
}
// account.drawing2(money);//情况4 //调用类的静态方法
// account.drawing3(money);//情况4
// account.drawing5(money, account);//情况5
}
}
添加synchronized的功能体现
最新推荐文章于 2022-12-06 10:39:57 发布