Java—线程安全

接上篇 :Java—线程基本使用_郑*杰的博客-优快云博客

一、线程安全模拟

1、线程安全主要存在于多个线程修改共享资源时出现问题,如下面的取钱案例


/**
 * 模拟取钱线程安全问题
 * 1、共同的账户类
 * 2、创建两个线程同时操作账户类
 * 3、账户类中实现取钱方法
 */
public class Test {

    public static void main(String[] args) {
        Acccount acc = new Acccount(100000);
        new DrawThread(acc,"小明").start();
        new DrawThread(acc,"小红").start();
    }
}

// 账户类
class Acccount {

    private double money;

    public Acccount(double money) {
        this.money = money;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public void drawmoeny(double money) {
        if(this.money >= 100000){
            System.out.println(Thread.currentThread().getName() + "来取钱");
            this.money -= money;
            System.out.println("余额为"+this.money);

        }else {
            System.out.println("余额不足");
        }
    }
}


// 线程类
class DrawThread extends Thread {

    private Acccount acc;
    public DrawThread(Acccount acc,String name){
        super(name);
        this.acc = acc;
    }


    @Override
    public void run() {
        acc.drawmoeny(100000);
    }
}

2、解决该类问题,在修改资源的节点加上锁,让线程依次修改资源后再释放给其他线程,其他非修改资源的操作是也属于多线程操作,但不影响安全。

二、 线程锁

2.1、方式一,同步代码块


// 账户类
class Acccount {
    private double money;

    public Acccount(double money) {
        this.money = money;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    /**针对核心代码加锁且指定对线程来说是唯一的对象,该对象可以理解一把锁,先拿到这把锁的线程即可执行锁下面的代码块
     实例方法通过使用对象本身,能保证同个对象使用自己的锁,从而不影响其他线程,例如如果该锁为常量(即字符串),
     那表示任意线程进来都会受这锁的影响,比如创建两个account对象,但实际上不同对象不应该相互影响,同个对象才会影响线程安全,
     因此规范写法如下实例方法,
     对于静态代码块,则需要使用类似常量的锁对象,因为该代码块是针对所有的线程,规范书写如下
     */

    public static void run(){
        synchronized(Acccount.class){
            System.out.println("静态代码块");
        }
    }

    public void drawmoeny(double money) {

        synchronized (this) {
            if (this.money >= 100000) {
                System.out.println(Thread.currentThread().getName() + "来取钱");
                this.money -= money;
                System.out.println("余额为" + this.money);

            } else {
                System.out.println("余额不足");
            }
        }
    }
}

2.2、方式二,同步方法


// 账户类
class Acccount {
    private double money;

    public Acccount(double money) {
        this.money = money;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }



    public synchronized static void run(){
        
            System.out.println("静态方法");
        
    }
    // 同步方法锁,synchronized装饰方法即可,静态代码同理
    public synchronized void drawmoeny(double money) {

        
            if (this.money >= 100000) {
                System.out.println(Thread.currentThread().getName() + "来取钱");
                this.money -= money;
                System.out.println("余额为" + this.money);

            } else {
                System.out.println("余额不足");
            }
        
    }
}


3、方式三,同步锁


class Acccount {
    private double money;
    private final Lock  lock = new ReentrantLock();// 定义一个同步锁,在相应的需要代码加锁并且解锁即可

    public Acccount(double money) {
        this.money = money;
    }
        
    public  void drawmoeny(double money) {
        lock.lock();
        try{
            if (this.money >= 100000) {
                System.out.println(Thread.currentThread().getName() + "来取钱");
                this.money -= money;
                System.out.println("余额为" + this.money);

            } else {
                System.out.println("余额不足");
            }
        }finally {
            lock.unlock();
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郑*杰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值