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

如有问题请指出,谢谢。








原文地址:https://www.cnblogs.com/mengjianzhou/p/5986861.html