zoukankan      html  css  js  c++  java
  • java并发编程 (一)synchronized关键字的使用

    在多个人对同一个程序进行访问时,可能会因为没有对该段程序进行并发处理,导致结果出现非预期结果

    下面以一个存钱取钱的程序为例:(此处不考虑手续费!!大笑

    package com.robert.bean;
    
    public class BankAccount 
    {
    	private int cardMoney = 1000;
    	private int cashMoney = 1000;
    
    	//存款
    	public void deposit(int number) 
    	{
    		cashMoney = cashMoney - number;
    		System.out.println("存款: 当前现金为:"+cashMoney+"$");
    		try {
     			Thread.sleep(500);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		cardMoney = cardMoney + number;
    		System.out.println("存款:当前卡上金额为:"+cardMoney+"$");
    
    	}
    
    	//取款
    	public void withdrawl(int number) 
    	{
    		cashMoney = cashMoney + number;
    		System.out.println("取款: 当前现金为:"+cardMoney+"$");
    		try {
    			Thread.sleep(500);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		cardMoney = cardMoney - number; 
    		System.out.println("取款: 当前卡上金额为:"+cashMoney+"$");
    	}
    	
    	public int getAmount()
    	{
    		return cardMoney + cashMoney;
    	}
    }
    

    package com.robert.test;
    
    import com.robert.bean.BankAccount;
    
    public class TestSynchronized implements Runnable 
    {
    	BankAccount bankAccount = new BankAccount();
    	public static void main(String[] args)
    	{
    		TestSynchronized testSync = new TestSynchronized();
    		Thread thread1 = new Thread(testSync);
    		Thread thread2 = new Thread(testSync);
    		thread1.start();
    		thread2.start();
    	}
    
    	public void run() {
    		for(int i=0;i<20;i++)
    		{
    			bankAccount.deposit(50);
    			bankAccount.withdrawl(40);
    		}
    		System.out.println("总金额为:"+bankAccount.getAmount());
    	}
    }
    
    卡上有1000元,手上有1000元现金

    现在进行存钱取钱操作,理论上不管怎么操作    卡上的钱+现金=2000

    但是运行该程序你会发现,会有总金额不是2000的结果

    显然说明该程序有误!

    而通过给方法加关键字synchronized就能解决这个小问题。

    修改后的程序如下所示

    package com.robert.bean;
    
    public class BankAccount 
    {
    	private int cardMoney = 1000;
    	private int cashMoney = 1000;
    
    	//存款
    	public synchronized void deposit(int number) 
    	{
    		cashMoney = cashMoney - number;
    		System.out.println("存款: 当前现金为:"+cashMoney+"$");
    		try {
     			Thread.sleep(500);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		cardMoney = cardMoney + number;
    		System.out.println("存款:当前卡上金额为:"+cardMoney+"$");
    
    	}
    
    	//取款
    	public synchronized void withdrawl(int number) 
    	{
    		cashMoney = cashMoney + number;
    		System.out.println("取款: 当前现金为:"+cardMoney+"$");
    		try {
    			Thread.sleep(500);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		cardMoney = cardMoney - number; 
    		System.out.println("取款: 当前卡上金额为:"+cashMoney+"$");
    	}
    	
    	public synchronized int getAmount()
    	{
    		return cardMoney + cashMoney;
    	}
    }
    

    在此通过这个小例子对该关键字进行简单的介绍:

    在java中synchronized有两种方法:

    1 synchronized方法

    2 synchronized声明

    对于加过synchronized关键字的方法会产生两种影响

    (1) 当一个线程正在执行一个synchronized的方法时,对于同一对象的调用该方法的其他线程将会被阻塞,直到第一个线程执行完毕。

    (2)当一个synchronized的方法存在时,那么该方法就会同调用该方法的对象的其他调用之间建立happens-before关系,以使其他的线程对当前对象可见。


    转载

    原文出自:http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

    如有问题请指出,谢谢。








  • 相关阅读:
    一些面试题(2)
    poj1102 7段数码管
    一些面试题(3)
    poj百练2737大整数除法
    枚举
    poj2244 约瑟夫环
    [Craftor原创]精通ModelSim脚本(1)
    [Craftor原创]带FIFO的UART收发器设计
    继电器的一些基本术语
    Every success is a creation for me
  • 原文地址:https://www.cnblogs.com/mengjianzhou/p/5986861.html
Copyright © 2011-2022 走看看