Java每日题- 线程安全初识

Java中的线程不完全问题:

  • 当多线程并发访问临界资源时,如果破坏了原子操作,可能会造成数据不一致。
  • 临界资源:共享资源(同一对象),一次仅允许一个线程使用,才可保证其正确性。
  • 原子操作:不可分割的多步操作,被视作一个整体,其步骤和顺序不可打乱或缺省。

举例子:最常见的例子就是银行取存款问题。
以下例子就是根据现实中银行卡的子母卡,丈夫,与妻子各一张卡为子母卡,同时取款会遇到的线程安全问题。
这里给出的解决方案是用同步代码块
synchronized(锁对象){
执行同步的代码块
}

public class TestSynchronized {
    public static void main(String[] args) {
        Account acc = new Account("6002","1234",2000); // 创建一个任务
        
        Thread husband = new Thread(new Husband(acc),"丈夫");//将任务加入丈夫进程
        
        Thread wife = new Thread(new Wife(acc),"妻子");//将任务加入妻子进程
        
        husband.start();// 执行丈夫进程
        wife.start();// 执行妻子进程
    }
}
class Wife implements Runnable{
    Account acc;    //账户对象的引用
    public Wife(Account acc) {
        this.acc = acc;
    }
    public void run() {
        this.acc.widthdrawal("6002", "1234", 1200); //掉用取款方法
    }
}
class Husband implements Runnable{
    Account acc;
    public Husband(Account acc) {
        this.acc = acc;
    }
    public void run() {
        this.acc.widthdrawal("6002", "1234", 1200); //掉用取款方法
    }
}
class Account{
    String cardNo;
    String password;
    double banlance;
    public Account(String cardNo, String password, double banlance) {
        this.cardNo = cardNo;
        this.password = password;
        this.banlance = banlance;
    }
    //取款
public void  widthdrawal(String no,String pwd,double money) {
        synchronized(this) {
        System.out.println(Thread.currentThread().getName()+"正在读卡...");
        if(no.equals(this.cardNo) && pwd.equals(this.password)) {
            System.out.println(Thread.currentThread().getName()+"验证成功...");
                if(money <= this.banlance) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    this.banlance = this.banlance-money;
                    System.out.println(Thread.currentThread().getName()+"取款成功!当前余额为:" + this.banlance);
                }else {
                    System.out.println("当前卡内余额不足!");
                }
        }else {
            System.out.println("银行卡密码错误");
        }
        }
    }
    
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容