Java同步锁全息详解

public class Account {
    private String accountNo;
    private double balance;
    public Account(String accountNo,double balance){
        this.accountNo=accountNo;
        this.balance=balance;
    }
    public double getBalance() {
        return balance;
    }
    public void setBalance(double balance) {
        this.balance = balance;
    }
    public String getAccountNo() {
        return accountNo;
    }
    public void setAccountNo(String accountNo) {
        this.accountNo = accountNo;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Account account = (Account) o;
        return accountNo.equals(account.accountNo);
    }
    @Override
    public int hashCode() {
        return accountNo.hashCode();
    }
}


public class DrawThread extends Thread {
    private Account account;
    private double drawAmount;
    public DrawThread(String name, Account account, double drawAmount) {
        super(name);
        this.account = account;
        this.drawAmount = drawAmount;
    }
    public void run(){
        synchronized (account){
            if(account.getBalance()>=drawAmount){
                System.out.println(getName() + "取钱成功,吐出钞票: " + drawAmount);
                try{
                    Thread.sleep(1);
                }catch(InterruptedException ex){
                    ex.getStackTrace();
                }
                account.setBalance(account.getBalance()-drawAmount);
                System.out.println("\t余额为:"+account.getBalance());
            }else{
                System.out.println(getName()+"取钱失败,余额不足");
            }
        }
    }
}


public class DrawTest {
    public static void main(String[] args){
        Account acct=new Account("1234567",1000);
        new DrawThread("甲",acct,800).start();
        new DrawThread("乙",acct,800).start();
    }
}


public class DrawThread extends Thread {
    private Account account;
    private double drawAmount;
    public DrawThread(String name, Account account, double drawAmount) {
        super(name);
        this.account = account;
        this.drawAmount = drawAmount;
    }
    public void run(){
//        synchronized (account){
            if(account.getBalance()>=drawAmount){
                System.out.println(getName() + "取钱成功,吐出钞票: " + drawAmount);
                try{
                    Thread.sleep(1);
                }catch(InterruptedException ex){
                    ex.getStackTrace();
                }
                account.setBalance(account.getBalance()-drawAmount);
                System.out.println("\t余额为:"+account.getBalance());
            }else{
                System.out.println(getName()+"取钱失败,余额不足");
            }
//        }
    }
}

会出现这些情况的结果:

public class Account {
    private String accountNo;
    private double balance;
    public Account(String accountNo,double balance){
        this.accountNo=accountNo;
        this.balance=balance;
    }
    //因为账户余额不可以随便更改,所以只为balance提供getter方法
    public double getBalance() {
        return balance;
    }
    public String getAccountNo() {
        return accountNo;
    }
    public void setAccountNo(String accountNo) {
        this.accountNo = accountNo;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Account account = (Account) o;
        return accountNo.equals(account.accountNo);
    }
    @Override
    public int hashCode() {
        return accountNo.hashCode();
    }
    //提供一个线程安全的draw()方法来完成取钱操作
    public synchronized void draw(double drawAmount){
        if(balance>=drawAmount){
            System.out.println(Thread.currentThread().getName()+"取钱成功!吐出钞票:"+drawAmount);
            try{
                Thread.sleep(1);
            }catch (InterruptedException ex){
                ex.printStackTrace();
            }
            balance-=drawAmount;
            System.out.println("\t余额为:"+balance);
        }else{
            System.out.println(Thread.currentThread().getName()+"取钱失败,余额不足");
        }
    }
}


public class DrawThread extends Thread {
    private Account account;
    private double drawAmount;
    public DrawThread(String name, Account account, double drawAmount) {
        super(name);
        this.account = account;
        this.drawAmount = drawAmount;
    }
    public void run(){
        account.draw(drawAmount);
    }
}


public class DrawTest {
    public static void main(String[] args){
        Account acct=new Account("1234567",1000);
        new DrawThread("甲",acct,800).start();
        new DrawThread("乙",acct,800).start();
    }
}


class X{
    //定义锁对象
    private final ReentrantLock lock=new ReentrantLock();
    //定义需要保证线程安全的方法
    public void m(){
        //加锁
        lock.lock();
        try{
            //...method body
        }
        //使用finally块来保证释放锁
        finally{
            lock.unlock();
        }
    }
}


public class Account {
    private final ReentrantLock lock=new ReentrantLock();
    private String accountNo;
    private double balance;
    public Account(String accountNo,double balance){
        this.accountNo=accountNo;
        this.balance=balance;
    }
    //因为账户余额不可以随便更改,所以只为balance提供getter方法
    public double getBalance() {
        return balance;
    }
    public String getAccountNo() {
        return accountNo;
    }
    public void setAccountNo(String accountNo) {
        this.accountNo = accountNo;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Account account = (Account) o;
        return accountNo.equals(account.accountNo);
    }
    @Override
    public int hashCode() {
        return accountNo.hashCode();
    }
    //提供一个线程安全的draw()方法来完成取钱操作
    public void draw(double drawAmount){
        //加锁
        lock.lock();
        try {
            if (balance >= drawAmount) {
                System.out.println(Thread.currentThread().getName() + "取钱成功!吐出钞票:" + drawAmount);
                try {
                    Thread.sleep(1);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
                balance -= drawAmount;
                System.out.println("\t余额为:" + balance);
            } else {
                System.out.println(Thread.currentThread().getName() + "取钱失败,余额不足");
            }
        }finally {
            lock.unlock();
        }
    }
}


class A{
    public synchronized void foo(B b){
        System.out.println("当前线程名为:"+Thread.currentThread().getName()+"进入了A实例的foo()方法");
        try{
            Thread.sleep(200);
        }catch(InterruptedException ex){
            ex.printStackTrace();
        }
        System.out.println("当前线程名为:"+Thread.currentThread().getName()+"试图调用B实例的last()方法");
        b.last();
    }
    public synchronized void last(){
        System.out.println("进入了A类的last()方法内部");
    }
}
class B{
    public synchronized void bar(A a){
        System.out.println("当前线程名为:"+Thread.currentThread().getName()+"进入了B实例的bar()方法");
        try{
            Thread.sleep(200);
        }catch(InterruptedException ex){
            ex.printStackTrace();
        }
        System.out.println("当前线程名为:"+Thread.currentThread().getName()+"试图调用A实例的last()方法");
        a.last();
    }
    public synchronized void last(){
        System.out.println("进入了B类的last()方法内部");
    }
}
public class DeadLock implements Runnable{
    A a =new A();
    B b=new B();
    public void init(){
        Thread.currentThread().setName("主线程");
        a.foo(b);
        System.out.println("进入了主线程之后...");
    }
    public void run(){
        Thread.currentThread().setName("副线程");
        b.bar(a);
        System.out.println("进入了副线程之后...");
    }
    public static void main(String[] args){
        DeadLock d1=new DeadLock();
        new Thread(d1).start();
        d1.init();
    }
}

结果:
Java同步锁全息详解的更多相关文章
- Java中String做为synchronized同步锁使用详解
		Java中使用String作同步锁 在Java中String是一种特殊的类型存在,在jdk中String在创建后是共享常量池的,即使在jdk1.8之后实现有所不同,但是功能还是差不多的. 借助这个特点 ... 
- Java分布式锁实现详解
		在进行大型网站技术架构设计以及业务实现的过程中,多少都会遇到需要使用分布式锁的情况.那么问题也就接踵而至,哪种分布式锁更适合我们的项目? 下面就这个问题,我做了一些分析: 分布式锁现状: 目前几乎很多 ... 
- “全栈2019”Java多线程第十六章:同步synchronized关键字详解
		难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ... 
- Java精通并发-自旋对于synchronized关键字的底层意义与价值分析以及互斥锁属性详解与Monitor对象特性解说【纯理论】
		自旋对于synchronized关键字的底层意义与价值分析: 对于synchronized关键字的底层意义和价值分析,下面用纯理论的方式来对它进行阐述,自旋这个概念就会应运而生,还是很重要的,下面阐述 ... 
- 《手把手教你》系列技巧篇(七十一)-java+ selenium自动化测试-自定义类解决元素同步问题(详解教程)
		1.简介 前面宏哥介绍了几种关于时间等待的方法,也提到了,在实际自动化测试脚本开发过程,百分之90的报错是和元素因为时间不同步而发生报错.本文介绍如何新建一个自定义的类库来解决这个元素同步问题.这样, ... 
- java.lang.Thread类详解
		java.lang.Thread类详解 一.前言 位于java.lang包下的Thread类是非常重要的线程类,它实现了Runnable接口,今天我们来学习一下Thread类,在学习Thread类之前 ... 
- Java并发关键字Volatile 详解
		Java并发关键字Volatile 详解 问题引出: 1.Volatile是什么? 2.Volatile有哪些特性? 3.Volatile每个特性的底层实现原理是什么? 相关内容补充: 缓存一致性协议 ... 
- java之StringBuffer类详解
		StringBuffer 线程安全的可变字符序列. StringBuffer源码分析(JDK1.6): public final class StringBuffer extends Abstract ... 
- Java内存模型(JMM)详解
		在Java JVM系列文章中有朋友问为什么要JVM,Java虚拟机不是已经帮我们处理好了么?同样,学习Java内存模型也有同样的问题,为什么要学习Java内存模型.它们的答案是一致的:能够让我们更好的 ... 
随机推荐
- mybatis多参数查询
			第三种比较好点 http://www.2cto.com/database/201409/338155.html 
- [Android Pro]   Android中全局Application的onCreate多次调用问题
			一般来说Application的onCreate方法只会执行一次, 如果应用中采用多进程方式,oncreate方法会执行多次,根据不同的进程名字进行不同的初始化, 就是在application中多添加 ... 
- Unity5.1 新的网络引擎UNET(九) UNET 官方推荐视频教程
			孙广东 2015.7.14 在新的网络引擎出现之前,Unity提供的是 内置 Raknet网络引擎, 这一次Unity想更新UGUI一样,花了大的手笔更新了, UNET. 原来的旧的网络组件 被提示 ... 
- Spark1.0.0 history server 配置
			在执行Spark应用程序的时候,driver会提供一个webUI给出应用程序的执行信息.可是该webUI随着应用程序的完毕而关闭port,也就是说,Spark应用程序执行完后,将无法查看应用程序的历史 ... 
- IOS 开发学习33 使用sqlite3
			sqlite3 命令行简单使用 sqlite3 路径 //打开数据库路径连接 select * from sqlite_master where type="table"; //显 ... 
- COSMOSBOX手遊制作手册(Word备份)
			20140712版 版本号 Version 日期 Date 作者 Author 变更主要原因描述 Brief Description 1.0 2014-4-26 陈霈霖 初稿 2.0 1. 前言 本手 ... 
- Protocol Informatics (PI项目)【基于网络轨迹的协议逆向工程文献学习】
			Protocol Informatics[基于网络轨迹的协议逆向工程文献学习]by tsy 声明: 1)本报告由博客园bitpeach撰写,版权所有,免费转载,请注明出处,并请勿作商业用途.恕作者著作 ... 
- 在Docker里使用(支持镜像继承的)supervisor管理进程(转)
			这篇文章是受 dockboard 之托帮忙翻译的与 docker 有关的技术文章.译自 Using Supervisor with Docker to manage processes (suppor ... 
- java分页功能代码
			import java.util.ArrayList; import java.util.List; /** * * @author cheney * * @date Aug 31, 2012 */ ... 
- SSH面试题目
			一简答 spring工作原理 为什么要用spring 3.请你谈谈SSH整合 4.介绍一下Spring的事务管理 5.Struct2基本流程 6.在Hibernate应用中Java对象的状态有哪些? ... 
