`
一路欢笑一路走
  • 浏览: 11169 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

线程同步-银行取款问题

阅读更多

1.取款问题

  比如你在银行里存了1000块,从银行柜台取出600,同时也在取款机取出600,正常的话第二次在取款机取款由于存款少于600所以取不出来,我们实践一下:


  银行账户类

  

public class BankAccount {
	int money=1000;
	public int getMoney(int num) {
		
		if ( money<num) {
			return -1;
		} else {
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			 money -= num;
			 System.out.println("剩了"+money);
			 return money;
		}
	}
}

  

 

   线程类

   

class ThreadBank extends Thread {

	BankAccount myAccount;

	ThreadBank(BankAccount myAccount) {
		this.myAccount = myAccount;
	}

	@Override
	public void run() {
		if(myAccount.getMoney(600)!=-1){
			System.out.println("取款成功");
		}else{
			System.out.println("余额不足,不能取款");
		}
	}
}

 

 

   测试类

   

public static void main(String[] args) {
		BankAccount myAccount= new BankAccount();
		ThreadBank  thread1=new ThreadBank(myAccount);
		ThreadBank  thread2=new ThreadBank(myAccount);
		thread1.start();
		thread2.start();}

 

 

  结果

  

剩了400
取款成功
剩了-200
取款成功

   

 

   从程序结果可以看出两次取钱都成功了,这就是线程同步导致的问题。

 

2.解决取款同步问题

      利用sychronized关键字解决同步问题,Synchronized关键字:

 

      synchronized关键字修饰一个方法的时候,该方法叫做同步方法。

Java中的每个对象都有一把锁(lock)或者监视器。当访问某个对象的synchronized方法时,表示将该对象上锁,此时其他任何线程都无法再访问该synchronied方法了,直到之前的那个线程执行方法完毕后(或者抛出了异常),那么将该对象的锁释放掉,其他线程才有可能再去访问该synchronized方法

   注意:如果一个对象有多个synchronized方法,某一时刻某个线程已经进入到某个synchronized方法,那么在该方法没有执行完毕前,其他线程是无法访问该对象的任何synchronized方法的。

  

   1)在getMoney方法前面加入synchronized加入关键字

   

public class BankAccount {
	int money=1000;
	public synchronized int getMoney(int num) {
		
		if ( money<num) {
			return -1;
		} else {
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			 money -= num;
			 System.out.println("剩了"+money);
			 return money;
		}
	}
}

  

  2) static synchronized方法

   如果某个synchronized方法是static的,那么当线程访问该方法时,它锁的并不是synchronized方法所在的对象,而是synchronized方法所在的对象所对应的Class对象,因为Java中无论一个类有多少个对象,这些对象会对应唯一一个Class对象,因此当线程分别访问同一个类的两个对象的两个static,synchronized方法时,他们的执行顺序也是顺序的,也就是说一个线程先去执行方法,执行完毕后另一个线程才开始执行

 

    静态synchronized方法

  

class Bank {

	public static synchronized void getMoney() {
		for (int i = 0; i < 10; i++) {
			System.out.println("=====  " + i);
		}
	}

 

   线程类

 

class ThreadStatic extends Thread {
	Bank bank;
	ThreadStatic(Bank bank) {
		this.bank = bank;
	}
	@Override
	public void run() {
		bank.getMoney();
	}
}

 

   测试类

   

public static void main(String[] args) {
		Bank bank1 = new Bank();

		Bank bank2 = new Bank();
		ThreadStatic thread1 = new ThreadStatic(bank1);
		ThreadStatic thread2 = new ThreadStatic(bank2);
	     thread1.start();
		thread2.start();
	}

 

   结果

   

=====  0
=====  1
=====  2
=====  3
=====  4
=====  5
=====  6
=====  7
=====  8
=====  9
=====  0
=====  1
=====  2
=====  3
=====  4
=====  5
=====  6
=====  7
=====  8
=====  9

  

    把static去掉,大家可以实践一下

   

   3)Synchronized块写法

  Synchronized(object){}表示线程执行的时候对object上锁

  

class ThreadStatic extends Thread {
	Bank bank;
	ThreadStatic(Bank bank) {
		this.bank = bank;
	}
	@Override
	public void run() {
		bank.getMoney();
	}
}

 This表示对本对象加锁

 

public static void main(String[] args) {
		Bank bank1 = new Bank();

		ThreadStatic thread1 = new ThreadStatic(bank1);

		ThreadStatic thread2 = new ThreadStatic(bank1);
		
		thread1.start();
		thread2.start();
	}

 两个线程调用同一个对象的方法,那么输出结果是什么呢,大家打印出来看一下,如果你没有写错的话,打印出来的结果肯定是按顺序执行的。

 

Synchronized方法和方法块写法区别:

Synchonized方法是一种粗粒度的并发控制,在某一时刻只能有一个线程执行该synchronized方法,synchronized块则是一种细粒度的并发控制,只会将块中的代码同步,位于方法内、synchronized块之外的代码是可以被多个线程同时访问到的

 

 

  

分享到:
评论

相关推荐

    银行账户的存取款线程设计

    银行账户的存取款线程设计银行账户的存取款线程设计

    以银行取钱为例模拟Java多线程同步问题完整代码

    主要介绍了以银行取钱为例模拟Java多线程同步问题完整代码,具有一定借鉴价值,需要的朋友可以参考下。

    互斥线程并发程序.zip

    简单实现线程的异步操作,简单易懂,下载VS2010 直接运行可看效果

    Java高级程序设计-多线程(二).pptx

    本章内容 掌握同步代码块的使用 掌握同步方法的使用 理解线程死锁 掌握 ThreadLocal 类的使用 使用多线程模拟猴子采花 使用同步方法模拟购票 使用多线程模拟购物订单生成 使用 ThreadLocal 类模拟银行取款 Java高级...

    使用Java多线程的同步机制编写应用程序.docx

    3.掌握多线程的同步机制。 实验内容 根据要求,编写应用程序。要求如下: 1.模拟银行账户,两个以上的用户同时进行存、取操作。 2.银行有一个账户,有两个用户分别向同一个账户存3000元,每次存1000,存三次。 3....

    模拟银行ATM机进行存取

    你多线程做的一个ATM模拟测试程序 (仅供参考)

    c语言下实现模拟ATM机的过程,包括存钱取钱、查询、积分等,可以同时管理5个账户

    c语言下实现模拟ATM机的过程,包括存钱取钱、查询、积分等,可以同时管理5个账户

    TestCommunicate.java

    JAVA线程同步通信银行存取款,银行账户的存取款线程设计,本例涉及银行账户类、存款类、取款类。实际意图是:使存钱和取钱构成一种关系——只有存钱后且账上有钱才能取钱,并且只有取钱后才能存钱。

    银行业务调度系统模拟

    此项目是对银行业务调度系统的模拟(也是一道面试题的解),附件中为VB源代码,直接在VB6的IDE中运行即可演示效果。

    Tomcat在Linux服务器上的BIO、NIO、APR模式设置方法

    同步 : 自己亲自出马持银行卡到银行取钱(使用同步IO时,Java自己处理IO读写)。 异步 : 委托一小弟拿银行卡到银行取钱,然后给你(使用异步IO时,Java将IO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS...

    软件工程-理论与实践(许家珆)习题答案

     ● 软件不存在磨损和老化问题,但存在退化问题;  ● 软件产品的生产主要是脑力劳动;  ● 软件产品的成本非常昂贵,其开发方式目前尚未完全摆脱手工生产方式; ● 软件具有“复杂性”,其开发和运行常受到...

    JAVA上百实例源码以及开源项目

     当用户发送第一次请求的时候,验证用户登录,创建一个该qq号和服务器端保持通讯连接得线程,启动该通讯线程,通讯完毕,关闭Scoket。  QQ客户端登录界面,中部有三个JPanel,有一个叫选项卡窗口管理。还可以更新...

    JAVA上百实例源码以及开源项目源代码

    Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个...

Global site tag (gtag.js) - Google Analytics