添加synchronized的功能体现

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
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值