线程安全~

什么是线性安全问题

多个线程同时操作同一个共享资源的时候可以会出现业务安全问题,称为线程安全问题
出现原因:1.存在多线程并发 2.同时访问共享资源 3.存在修改共享资源
在这里插入图片描述

共同账户取钱问题(存在线程安全问题)

public class ATMTest {
    public static void main(String[] args)throws Exception {
        //共同账户
        Account account = new Account();
        FutureTask f1 = new FutureTask(new Get(account));
        Thread thread1 = new Thread(f1);
        FutureTask f2 = new FutureTask(new Get(account));
        Thread thread2 = new Thread(f2);
        thread1.start();
        thread2.start();
        System.out.println((Integer) f1.get());
        System.out.println((Integer) f2.get());
        System.out.println(account.getAnInt());


    }
}

@Getter
@Setter
class Account{
    private Integer anInt = 10000;

    public Integer getMoney(int i){
        if (anInt>i){
            anInt = anInt - i;
            return i;
        }else {
            System.out.println("余额不足");
            return null;
        }
    }
}

class Get implements Callable<Integer>{

    private Account account;

    public Get(Account account) {
        this.account = account;
    }

    @Override
    public Integer call() throws Exception {
        System.out.println(Thread.currentThread().getName()+"输入您要取的钱数:");
        int i = new Scanner(System.in).nextInt();
        return account.getMoney(i);
    }
}

线程同步

为了解决线程安全问题
让多个线程依次访问共享资源,解决安全问题
线程同步的核心思想:
加锁,把共享资源上锁,每次只能一个进程进入访问完毕以后解锁,然后其他线程才能进来

方式一:同步代码块

在这里插入图片描述

public class ATMTest {
    public static void main(String[] args)throws Exception {
        //共同账户
        Account account = new Account();
        FutureTask f1 = new FutureTask(new Get(account));
        Thread thread1 = new Thread(f1);
        FutureTask f2 = new FutureTask(new Get(account));
        Thread thread2 = new Thread(f2);
        thread1.start();
        thread2.start();
        System.out.println((Integer) f1.get());
        System.out.println((Integer) f2.get());
        System.out.println(account.getAnInt());


    }
}

@Getter
@Setter
class Account{
    private Integer anInt = 10000;

    public Integer getMoney(int i){
        synchronized ("ccc") {
            if (anInt>i){
                anInt = anInt - i;
                return i;
            }else {
                System.out.println("余额不足");
                return null;
            }
        }
    }
}

class Get implements Callable<Integer>{

    private Account account;

    public Get(Account account) {
        this.account = account;
    }

    @Override
    public Integer call() throws Exception {
        System.out.println(Thread.currentThread().getName()+"输入您要取的钱数:");
        int i = new Scanner(System.in).nextInt();
        return account.getMoney(i);
    }
}

锁对象不能用任意的无关对象,不然会影响其他无关进程的执行
锁对象的规范要求:
规范上:建议使用共享资源作为锁对象
对于实例方法建议使用this作为锁对象
对于静态方法建议使用字节码(类名.class)对象作为锁对象(因为静态方法在内存中是唯一的,所以直接使用类名上锁)

方式二:同步方法

在这里插入图片描述

在这里插入图片描述

方式三:Lock锁

在这里插入图片描述

public class ATMTest {
    public static void main(String[] args)throws Exception {
        //共同账户
        Account account = new Account();
        FutureTask f1 = new FutureTask(new Get(account));
        Thread thread1 = new Thread(f1);
        FutureTask f2 = new FutureTask(new Get(account));
        Thread thread2 = new Thread(f2);
        thread1.start();
        thread2.start();
        System.out.println((Integer) f1.get());
        System.out.println((Integer) f2.get());
        System.out.println(account.getAnInt());


    }
}

@Getter
@Setter
class Account{
    private Integer anInt = 10000;
    private final Lock lock =new ReentrantLock(); //锁对象,唯一,不可修改

    public Integer getMoney(int i){
        lock.lock();
        try {
            if (anInt>i){
                anInt = anInt - i;
                return i;
            }else {
                System.out.println("余额不足");
                return null;
            }
        } finally {
            lock.unlock();
        }
    }
}


class Get implements Callable<Integer>{

    private Account account;

    public Get(Account account) {
        this.account = account;
    }

    @Override
    public Integer call() throws Exception {
        System.out.println(Thread.currentThread().getName()+"输入您要取的钱数:");
        int i = new Scanner(System.in).nextInt();
        return account.getMoney(i);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值