zoukankan      html  css  js  c++  java
  • 线程的同步

    由于同一个进程的多个线程共享存储空间,在带来方便的同时也产生了一些访问冲突的问题。如果两个线程同时访问一个共享变量(如例子中的余额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 + "元,
    目前余额为:" + bank.getBalance() + "元。");
                        System.out.println("****************************");
                    }else {
                        System.out.println("余额不足!");
                    }
                } else {
                    bank.setBalance(bank.getBalance() + amount);
                    System.out.println("*********************************");
                    System.out.println("已存入" + amount + "元,
    目前余额为:" + 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;
        }
    }
    

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

  • 相关阅读:
    项目报错二
    项目报错一
    OCP-1Z0-051-V9.02-21题
    Windows API——OpenClipboard——剪切板
    如果在CEdit中实现Ctrl+V、Ctrl+C、Ctrl+X的功能
    OCP-1Z0-051-V9.02-18题
    OCP-1Z0-051-V9.02-17题
    OCP-1Z0-051-V9.02-15题
    OCP-1Z0-051-V9.02-14题
    OCP-1Z0-051-V9.02-12题
  • 原文地址:https://www.cnblogs.com/HelloBigTable/p/10830866.html
Copyright © 2011-2022 走看看