synchronized方法验证,不要被谬论迷惑

       以前编程没有怎么接触过synchronized方法,不太了解,今天编程遇到了多个线程访问同一个共享资源的问题,google了下synchronized使用方法,网上有二种说法,第一种说法是当一个线程访问了某个对象中的synchronzied方法,其它线程可以继续访问其它的synchronized方法,第二个说法与第一种说法相反,不能访问。搞的我也不确定,更要命的是,这两种说法在网上一边又一边的转载,以讹传讹,要误导不少java新手。到底那一个是正确的,编个程序验证就清楚了

   下面是一个示例程序,有三个角色,一个家庭中的父亲,母亲,和儿子,同时在ATM取款机上向同一个银行账号进行取钱和查询的操作
1.银行类

  

package com.sunnylocus.test;

public class Bank  {
	private int money = 100;
	//取钱
	public synchronized void takeMoney(int num) {
			Thread.sleep(1000 * 5);   //取钱需要5秒
			money -= num;
	}
	//存钱
	public synchronized void addMoney(int num) {
			Thread.sleep(1000 * 10); //存钱需要10秒
			money += money;
	}
	//查询
	public int queryMoney() {
		return money;
	}
}

 

 


2.父亲类

package com.sunnylocus.test;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Father extends Thread{
	private Bank bank;
	private int num;
	
	DateFormat dateFormate = new SimpleDateFormat("a h:mm:ss");  //日期格式对象
	
	public Father(Bank bank,int num) {
		this.bank = bank;
		this.num = num;
	}

	public void run() {
		System.out.println("老爸正在取钱...      --"+dateFormate.format(new Date()));
		bank.takeMoney(num);
		System.out.println("老爸取走了"+num +"         --"+dateFormate.format(new Date()));
	}
	
}



3.母亲类

package com.sunnylocus.test;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Monther extends Thread{
	private Bank bank;
	private int num;
	DateFormat dateFormate = new SimpleDateFormat("a h:mm:ss");  //日期格式对象
	
	public Monther(Bank bank,int num) {
		this.bank = bank;
		this.num = num;
	}

	public void run() {
		System.out.println("老妈正在取钱....         "+dateFormate.format(new Date()));
		bank.takeMoney(num);
		System.out.println("老妈取走了"+num+"         --"+dateFormate.format(new Date()));
	}
	
}



4.儿子类

package com.sunnylocus.test;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Sun extends Thread{
	private Bank bank;
	DateFormat dateFormate = new SimpleDateFormat("a h:mm:ss");  //日期格式对象
	public Sun(Bank bank) {
		this.bank = bank;
	}

	public void run() {
		//查询余款
		System.out.println("儿子查询余额:"+bank.queryMoney() +"     --"+dateFormate.format(new Date()));
	}
}



5.测试类

package com.sunnylocus.test;

public class Main {
	public static void main(String[] args) {
		//银行
		Bank bank = new Bank();
		//老爸
		Father father = new Father(bank,50);
		//老妈
		Monther monther = new Monther(bank,100);
		//儿子
		Sun sun = new Sun(bank);
		
		new Thread(father).start();
		new Thread(monther).start();
		new Thread(sun).start();
		
	}
}


输出结果:

老爸正在取钱...               --上午 11:52:01
老妈正在取钱....              --上午 11:52:01
儿子查询余额:100           --上午 11:52:01

老爸取走了50                 --上午 11:52:06
老妈取了30                    --上午 11:52:11


   一共有三个线程,同时启动,父亲线程和母亲线程同时取款的操作,因为父亲线程已经占用了对象锁,所以母亲线程只能等到父亲执行完方法释放锁后,才能执行。即便父亲线程占用了对象锁,儿子线程也能调用非synchronzied方法
 

     我们把母亲类的取钱的方法改成存钱的操作,虽然不是同一个synchronized方法.也一样不能执行,必须等到父亲线程方法执行完毕后,才能进行存钱的操作

我的结论: 
     synchronized method(){}可以防止多个线程同时访问这个对象的synchronized方法,如果一个对象有多个synchronized方法,只要一个线 程访问了其中的一个synchronized方法且没有释放对象锁,那么其它线程不能同时访问这个对象中的任何一个synchronized方法,但可以访问这个对象中的非synchronized方法。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值