对synchronized关键字的理解
先看两个线程同时访问一个对象的例子.
public class Account {
    private String accountNo;
    private double balance;
    public Account() {
    }
    public Account(String accountNo, double balance) {
        this.accountNo = accountNo;
        this.balance = balance;
    }
    public void setAccountNo(String accountNo) {
        this.accountNo = accountNo;
    }
    public String getAccountNo() {
        return this.accountNo;
    }
    public void setBalance(double balance) {
        this.balance = balance;
    }
    public double getBalance() {
        return this.balance;
    }
}
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;
    }
    @Override
    public void run() {
        if (account.getBalance() >= drawAmount) {
            System.out.println(getName() +
                    "取钱成功!吐出钞票:" + drawAmount);
            account.setBalance(account.getBalance() - drawAmount);
            System.out.println("\t余额为: " + account.getBalance());
        } else {
            System.out.println(getName() + "取钱失败!余额不足!");
        }
    }
}
public class TestDraw {
    public static void main(String[] args) {
        Account acct = new Account("1234567", 1000);
        new DrawThread("甲", acct, 800).start();
        new DrawThread("乙", acct, 800).start();
    }
}
类Account有2个成员变量,帐户名字和余额.DrawThread中的取钱逻辑很简单.先判断余额够不够,如果够,正常取钱,不够的话报余额不足.在TestDraw同时开2个线程取钱,这时候可能会有问题,线程甲判断出还能取钱,准备执行account.setBalance时放弃了处理器,线程乙获得了处理器,判断钱够不够.因为之前线程甲还没有修改balance的值,所以认为可以取钱.所以线程乙取了钱,之后放弃处理器.线程甲之前已经判断过可以取钱,就执行取钱逻辑,这时候帐户余额就变成负的了.多次运行该程序,肯定会出现不正常的现象.
synchronized就是为了解决类似的问题.把DrawThread改成如下形式:
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;
    }
    @Override
    public void run() {
        synchronized (account) {
            if (account.getBalance() >= drawAmount) {
                System.out.println(getName() +
                        "取钱成功!吐出钞票:" + drawAmount);
                account.setBalance(account.getBalance() - drawAmount);
                System.out.println("\t余额为: " + account.getBalance());
            } else {
                System.out.println(getName() + "取钱失败!余额不足!");
            }
        }
    }
}
synchronized (account){}表示锁住account对象,一个对象访问account时,另外一个对象不能访问.这就保证了线程安全.
对synchronized关键字的理解的更多相关文章
- Java synchronized关键字的理解
		转载自:http://blog.csdn.net/xiao__gui/article/details/8188833 在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环 ... 
- Android进阶——多线程系列之wait、notify、sleep、join、yield、synchronized关键字、ReentrantLock锁
		多线程一直是初学者最困惑的地方,每次看到一篇文章,觉得很有难度,就马上叉掉,不看了,我以前也是这样过来的.后来,我发现这样的态度不行,知难而退,永远进步不了.于是,我狠下心来看完别人的博客,尽管很难但 ... 
- 深入理解java中的synchronized关键字
		synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D ... 
- java之结合代码理解synchronized关键字
		为了保证数据的一致性即实现线程的安全性,java虚拟机提供了同步和锁机制.synchronized关键字是最基本的互斥同步手段.除此之外,还可以使用java.util.concurrent包中的重入锁 ... 
- Java精通并发-透过字节码理解synchronized关键字
		在上一次https://www.cnblogs.com/webor2006/p/11428408.html中对于synchronized关键字的作用做了一个实例详解,下面再来看一下这个程序: 请问下, ... 
- Java中synchronized关键字理解
		好记性不如烂笔头~~ 并发编程中synchronized关键字的地位很重要,很多人都称它为重量级锁.利用synchronized实现同步的基础:Java中每一个对象都可以作为锁.具体表现为以下三种形式 ... 
- 从分布式锁角度理解Java的synchronized关键字
		分布式锁 分布式锁就以zookeeper为例,zookeeper是一个分布式系统的协调器,我们将其理解为一个文件系统,可以在zookeeper服务器中创建或删除文件夹或文件.设D为一个数据系统,不具备 ... 
- java 多线程 Synchronized方法和方法块 synchronized(this)和synchronized(object)的理解
		synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法:通过在方法声明中加入 synchronized ... 
- Java多线程系列--“基础篇”04之 synchronized关键字
		概要 本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchro ... 
随机推荐
- jquey插件开发
			1.概述 jquery插件开发的主要方法有三种: 1.通过$.extend()来扩展jQuery,即在jQuery命名空间下扩展属性,直接在$对象下调用,不需要再dom下调用,也无法在dom元素下调用 ... 
- Servlet_ResponseHeader
			protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletExcepti ... 
- js获取前之前或之后的日期
			function fun_date(aa){ var date1 = new Date(), time1=date1.getFullYear()+"-"+(date1.getMon ... 
- js 匿名函数 json
			<script type="text/javascript"> var My_func = function(name){ this.obj_name=name; ... 
- java  对象比较
			class Book{ private String title ; private double price ; public Book(String title , double pr ... 
- 有限状态机(Finite-state machine)
			var menu = { // 当前状态 currentState: 'hide', // 绑定事件 initialize: function() { var self = this; self.on ... 
- 全局文件 pch
			在 bulding setting 里面 搜 prefix header 然后添加自己的pch 路径, 类似 $(SRCROOT)/... 还要把 precompile prefix header 设 ... 
- GOLang(数组操作随篇)
			创建一个类似PHP Array $data["userInfo"] = ["name"=>"Josn","ages" ... 
- PHP header( ) 禁止页面后退
			header("Cache-control:no-cache,no-store,must-revalidate"); header("Pragma:no-cache&qu ... 
- centos 6.5下cmake工具的安装与配置
			一.cmake是什么? CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程).他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C+ ... 
