用synchronized解决简单的线程安全问题

线程安全问题
当多个线程同时操作堆区或者方法区的某个数据时,可能会出现数据不一致的现象,成为线程安全问题
以多人从同一个账户中取钱作为例子:
账户类

public class BankAccount {
    int balance = 10000;   //账户余额(万元)

    //取钱操作,约定每次取钱1000万
    public void withdraw() {
        System.out.println(Thread.currentThread().getName() + "取钱前,查询余额:" + balance + "万元");
        balance -= 1000;
        System.out.println(Thread.currentThread().getName() + "取了1000万后余额:" + balance + "万元");

    }
}

线程类

/*
*
* 创建线程类,模拟人从账户中取钱
*
* */
public class PersonThread extends Thread {
    private BankAccount account;     //银行账户


    public PersonThread(BankAccount account) {
        super();
        this.account = account;
    }


    @Override
    public void run() {
        account.withdraw();
    }
}

测试类

/*
*
* 使用线程模拟多人同时从某个账户中取钱
*
* */
public class Test {
    public static void main(String[] args) {

        //先开户
        BankAccount account = new BankAccount();

        //创建三个线程,模拟三个人取钱
        PersonThread p1 = new PersonThread(account);
        PersonThread p2 = new PersonThread(account);
        PersonThread p3 = new PersonThread(account);

        p1.setName("bingbing");
        p2.setName("yuanyuan");
        p3.setName("jianjian");

        p1.start();
        p2.start();
        p3.start();
        /*
        *
        * 运行当前程序,可能会出现数据不一致情况,这就是线程安全问题
        *
        * */
    }
}

以上程序的运行结果会出现这样的情况
在这里插入图片描述
在查询的时候显示的都是一样的结果,但是在取钱之后结果就不一样,这就出现了线程安全问题
当出现线程安全问题的时候可以通过,让每个线程都访问自己的局部变量,或者在多个线程必须同时操作实例变量/静态变量时采用线程同步技术
我们将账户类稍作修改

public class BankAccount {
    int balance = 10000;   //账户余额(万元)

    private static final Object OBJ = new Object();       //定义了一个常量

    //取钱操作,约定每次取钱1000万
    public void withdraw() {
        synchronized (OBJ) {       //经常使用一个常量对象作为锁对象
            System.out.println(Thread.currentThread().getName() + "取钱前,查询余额:" + balance + "万元");
            balance -= 1000;
            System.out.println(Thread.currentThread().getName() + "取了1000万后余额:" + balance + "万元");
        }
    }
}

然后再运行测试类
在这里插入图片描述
这样就通过synchronized解决了一个简单的线程安全问题
介绍一下synchronized语法和工作原理:
synchronized(锁对象){
同步代码块
}
工作原理:
1)任意对象都可以作为锁对象,每个对象有一个内置锁
2)某一时刻,锁对象最多只能被一个线程持有
3)如果线程获得了锁对象后,会一直持有,知道执行完同步代码块后才释放
4)线程要执行同步代码块,必须先获得锁对象
场景描述:假设有线程A和线程B都想要执行同步代码块
1)线程A获得CPU执行权,获得锁对象后,开始执行同步代码块
2)线程A在执行同步代码块期间,CPU执行权被线程B抢走了,线程A转为就绪状态
3)线程B获得CPU执行权,也想要执行同步代码块,必须先获得锁对象,现在锁对象被线程A持有,线程B转到等待锁对象池中进行阻塞
4)线程A重新获得CPU执行权,执行完同步代码块后释放锁对象
5)等待锁对象池中的线程B获得了锁对象,转为就绪状态

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值