首页 > 编程语言 > 详细

线程的同步

时间:2019-05-08 11:56:11      阅读:127      评论:0      收藏:0      [点我收藏+]

由于同一个进程的多个线程共享存储空间,在带来方便的同时也产生了一些访问冲突的问题。如果两个线程同时访问一个共享变量(如例子中的余额balance),会造成最终结果不符合实际需求的情况。

Java中引入了“对象互斥锁”的概念(又称为监视器)来实现不同线程对共享数据操作的同步。“对象互斥锁”不允许多个线程对象同时访问同一个条件变量,即同一时刻最多只有一个线程对象访问共享数据。

我们通过private修饰变量,让变量只能被方法访问,所以针对方法提出一套机制——synchronized关键字,它包含两种用法:synchronized修饰方法和synchronized修饰程序快。

一、synchronized修饰方法

  格式:public synchronized void withdrawal(double amount){}

  该机制保证了同一时刻内,一个类实例中所有声明synchronized的方法最多只有一个处于可执行的状态,从而避免了类成员变量的访问冲突。

  所以synchronized只用修饰会访问共享变量的方法即可,而常规方法不用,synchronized修饰方法的案例请看“线程的通信中第一个例子”。

二、synchronzed修饰程序块

  格式:synchronized(syncObject){

     //允许访问控制的代码

     }

  synchronized程序块是对一个类实例对象进行上锁,保证该类实例对象同一时刻只能被一个线程访问。代码如下:

public class BankDriver {
    public static void main(String[] args) {
        //初始化一个银行账号,余额为2000
        Bank bank = new Bank("001", 2000);

        //开启两个Operation线程对象对bank账号进行取款操作
        for (int i=0;i<2;i++){
            new Operation(i+"#",bank, (double) 1200,1).start();
        }
    }
}

public class Operation extends Thread {
    //定义银行账户对象、操作金额变量、存取款flag(1代表取款,0代表存款)
    Bank bank;
    double amount;
    int flag;

    public Operation(String name) {
        super(name);
    }

    public Operation(String name,Bank bank,Double amouot,int flag){
        super(name);
        this.bank = bank;
        this.amount = amouot;
        this.flag = flag;
    }

    @Override
    public void run() {
        //将bank设置为上锁对象,通过flag判断是存款还是取款执行对应逻辑
        synchronized(bank){
            if (flag == 1) {
                if (bank.getBalance() >= amount){
                    System.out.println("****************************");
                    bank.setBalance(bank.getBalance() - amount);
                    System.out.println("已取出" + amount + "元,\n目前余额为:" + bank.getBalance() + "元。");
                    System.out.println("****************************");
                }else {
                    System.out.println("余额不足!");
                }
            } else {
                bank.setBalance(bank.getBalance() + amount);
                System.out.println("*********************************");
                System.out.println("已存入" + amount + "元,\n目前余额为:" + bank.getBalance() + "元。");
                System.out.println("*********************************");
            }
        }
    }
}

public class Bank {
    //账户id和余额
    private String bankID;
    private double balance;

    public Bank() {
    }

    public Bank(String bankID, double balance) {
        this.bankID = bankID;
        this.balance = balance;
    }

    public String getBankID() {
        return bankID;
    }

    public void setBankID(String bankID) {
        this.bankID = bankID;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }
}

  结果如下:如果没有设置线程同步机制,可能会造成余额为负。

技术分享图片

 

线程的同步

原文:https://www.cnblogs.com/HelloBigTable/p/10830866.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!