先看两个线程同时访问一个对象的例子.

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关键字的理解的更多相关文章

  1. Java synchronized关键字的理解

    转载自:http://blog.csdn.net/xiao__gui/article/details/8188833 在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环 ...

  2. Android进阶——多线程系列之wait、notify、sleep、join、yield、synchronized关键字、ReentrantLock锁

    多线程一直是初学者最困惑的地方,每次看到一篇文章,觉得很有难度,就马上叉掉,不看了,我以前也是这样过来的.后来,我发现这样的态度不行,知难而退,永远进步不了.于是,我狠下心来看完别人的博客,尽管很难但 ...

  3. 深入理解java中的synchronized关键字

    synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D ...

  4. java之结合代码理解synchronized关键字

    为了保证数据的一致性即实现线程的安全性,java虚拟机提供了同步和锁机制.synchronized关键字是最基本的互斥同步手段.除此之外,还可以使用java.util.concurrent包中的重入锁 ...

  5. Java精通并发-透过字节码理解synchronized关键字

    在上一次https://www.cnblogs.com/webor2006/p/11428408.html中对于synchronized关键字的作用做了一个实例详解,下面再来看一下这个程序: 请问下, ...

  6. Java中synchronized关键字理解

    好记性不如烂笔头~~ 并发编程中synchronized关键字的地位很重要,很多人都称它为重量级锁.利用synchronized实现同步的基础:Java中每一个对象都可以作为锁.具体表现为以下三种形式 ...

  7. 从分布式锁角度理解Java的synchronized关键字

    分布式锁 分布式锁就以zookeeper为例,zookeeper是一个分布式系统的协调器,我们将其理解为一个文件系统,可以在zookeeper服务器中创建或删除文件夹或文件.设D为一个数据系统,不具备 ...

  8. java 多线程 Synchronized方法和方法块 synchronized(this)和synchronized(object)的理解

    synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法:通过在方法声明中加入 synchronized ...

  9. Java多线程系列--“基础篇”04之 synchronized关键字

    概要 本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchro ...

随机推荐

  1. 数据库 Mysql事务详解

    Mysql事务 mysql的事务默认是自动提交的,也就是你提交一个query,他就直接执行!我们可以通过 禁止自动提交 开启自动提交 //mysql事务 #include <stdio.h> ...

  2. css强制折行和隐藏超出部分

    一.强制换行1 word-break: break-all; 只对英文起作用,以字母作为换行依据. 2 word-wrap: break-word; 只对英文起作用,以单词作为换行依据. 3 whit ...

  3. 微信小程序之----问题

    1.如何定义全局数据 在app.js的App({})中定义的数据或函数都是全局的,在页面中可以通过var app = getApp();  app.function/key的方式调用,不过我们没有必要 ...

  4. mysql,mybatis使用中遇到的类型转化的问题

    产生原因还没有明白,先记录一下. 使用DATEDIFF函数,计算两个日期的时间差.在mybatis中,resultType 是map.在代码中,根据map的key取值的时候. 在mysql 5.5.3 ...

  5. 获取IIS版本

    近日,有一项目要分别获取iis6.0和7.5,然后对进程进行操作~ 研究良久,有以下办法获取iis版本. 代码: DirectoryEntry getEntity = new DirectoryEnt ...

  6. [Angular Tutorial] 9 -Routing & Multiple Views

    在这一步中,您将学到如何创建一个布局模板,并且学习怎样使用一个叫做ngRoute的Angular模块来构建一个具有多重视图的应用. ·当您现在访问/index.html,您将被重定向到/index.h ...

  7. //@sourceURL=filename.js

    在 console 中输入代码的最后一行加上 //@ sourceURL=filename.js, 会在 Scripts 面板中有个叫 filename.js 的文件, 然后他就和外部 js 文件一样 ...

  8. iOS 之 NSString 去除前后空格和回车键

    NSString *string = @" spaces in front and at the end "; NSString *trimmedString = [string ...

  9. window 2008+apache2.4.4+php5.5+mysql-5.6.12+phpmyadmin4.0.4.1安装过程(参考他人文章基础上加上自己遇到的问题)

    一.window server2008的安装 1.我用U盘安装的,先用UltraISO把server2008刻录到U盘中,过程我搜了一下,帖个地址: http://wenku.baidu.com/vi ...

  10. jQuery动画高级用法(上)——详解animation中的.queue()动画队列插队函数

    决定对animate方面做一些总结,希望能给大家一些启发和帮助 从一个实际应用谈起 今天不谈animate().fadeIn().fadeOut().slideUp().show().hide()诸如 ...