Java 线程同步互斥

概要:

本实例模拟银行ATM(存)取款机,分析一个用户往ATM(存)取款机中存钱时,另一个用户在另一个地方从中取钱,存在操作前后不一致,程序采用线程同步与非同步方法解决的区别。

| |目录

技术要点

    运用线程的互斥的技术要点如下:

  • 在类的方法声明中使用synchronized关键字可以保证在同一时刻只有一个线程能够进入该方法。

  • synchronized可以出现在代码块中,表示同一时刻只有一个线程能够进入该段代码。

代码实现

package net.xsoftlab.baike;
class Bank {
	private double current_money = 500.0d; // 存入银行的钱数
	public void putNonSynDeposit(double putMoney) {// 存钱没有采用同步机制
		System.out.println("没有采用线程同步机制,钱为" + this.current_money + "; 存钱: "
				+ putMoney);
		System.out.println("等待中......");// 存钱时先等待300毫秒
		try {
			Thread.sleep(300);// 线程休眠
		} catch (Exception e) {// 捕获异常
			e.printStackTrace();
		}
		System.out.println("等待完毕进行存钱操作...");
		this.current_money = this.current_money + putMoney;
		System.out.println("没有采用线程同步机制,当前钱数为" + this.current_money + "元");
	}
	public void takeNonSynWithdraw(double takeMoney) {// 取钱没有同步机制
		System.out.println("没有采用线程同步机制,钱为" + this.current_money + "; 取钱: "
				+ takeMoney);
		System.out.println("等待中......");// 取钱时先等待500毫秒
		try {
			Thread.sleep(500);// 线程休眠
		} catch (Exception e) {// 捕获异常
			e.printStackTrace();
		}
		System.out.println("等待完毕进行取钱操作...");
		this.current_money = this.current_money - takeMoney;
		System.out.println("没有采用线程同步机制,当前钱数为" + this.current_money + "元");
	}
	public synchronized void putSynDeposit(double putMoney) {// 存钱有同步机制
		System.out.println("采用线程同步机制,钱为" + this.current_money + "; 存钱: "
				+ putMoney);
		System.out.println("等待中......");// 存钱时先等待300毫秒
		try {
			Thread.sleep(300);// 线程休眠
		} catch (Exception e) {// 捕获异常
			e.printStackTrace();
		}
		System.out.println("等待完毕进行存钱操作...");
		this.current_money = this.current_money + putMoney;
		System.out.println("采用线程同步机制,当前钱数为" + this.current_money + "元");
	}
	public synchronized void takeSynWithdraw(double takeMoney) {// 取钱有同步机制
		System.out.println("采用线程同步机制,钱为" + this.current_money + "; 取钱: "
				+ takeMoney);
		System.out.println("等待中......");// 取钱时先等待500毫秒
		try {
			Thread.sleep(500);// 线程休眠
		} catch (Exception e) {// 捕获异常
			e.printStackTrace();
		}
		System.out.println("等待完毕进行取钱操作...");
		this.current_money = this.current_money - takeMoney;
		System.out.println("采用线程同步机制,当前钱数为" + this.current_money + "元");
	}
}
class AccessBank extends Thread {// 继承Thread类实现线程方法
	private Bank bank = null; // 待访问的帐号对象
	private String method = ""; // 访问帐号的方法
	public AccessBank(Bank account, String method) {// 构造方法进行初始化
		this.method = method;
		this.bank = account;
	}
	public void run() {// 实现Thread的方法
		if (method.equals("putNonSynDeposit")) {// 不同参数调用不同的方法
			bank.putNonSynDeposit(500.0);
		} else if (method.equals("takeNonSynWithdraw")) {
			bank.takeNonSynWithdraw(200.0);
		} else if (method.equals("putSynDeposit")) {
			bank.putSynDeposit(500.0);
		} else if (method.equals("takeSynWithdraw")) {
			bank.takeSynWithdraw(200.0);
		}
	}
}
public class TextSynchronized {// 操作展示线程同步与非同步区别的类
	public static void main(String[] args) {// java程序主入口处
		Bank bank = new Bank();// 实例化对象
		System.out.println("1.未采用同步机制时...");
		Thread putMoney = new AccessBank(bank, "putNonSynDeposit");// 存钱没有采用同步机制
		Thread takeMoney = new AccessBank(bank, "takeNonSynWithdraw");// 取钱没有同步机制
		putMoney.start();// 启动线程
		takeMoney.start();// 启动线程
		try {
			putMoney.join();// 等待两线程运行结束
			takeMoney.join();
		} catch (Exception e) {// 捕获异常
			System.out.println("两线程运行出错:" + e.getMessage());
		}
		System.out.println();
		bank = new Bank();
		System.out.println("2.采用同步机制时...");
		putMoney = new AccessBank(bank, "putSynDeposit");// 存钱有同步机制
		takeMoney = new AccessBank(bank, "takeSynWithdraw");// 取钱有同步机制
		putMoney.start();// 启动线程
		takeMoney.start();// 启动线程
	}
}

程序解读

  1. Java中的线程同步可以通过synchronized关键字来实现,synchronized既可以修饰变量(必须是类对象),又可以修饰方法。被synchronized修饰的变量和方法同时只能有一个线程来操作,其他线程只能等待,以此达到线程同步的目的。synchronized结构:synchronized(obj){...//操作代码}。

  2. Bank类的putNonSynDeposit()方法实现存钱功能没有使用同步互斥技术。允许多个用户同时存钱或取钱,这样就会出错。takeNonSynWithdraw()方法实现取钱功能没有使用同步互斥技术,这样也可能由于多个用户同时操作会出错。

  3. putSynDeposit()方法实现使用同步互斥存钱的功能,即在同一时刻只允许一个用户(线程)进行操作,当该线程进入同步方法后对象被锁,其他线程因为没有对象锁而不能访问该对象的该方法,只有当持有对象锁的线程释放锁时,才有机会访问该方法。也就是当多个用户同时存钱时也都是顺序执行的,不会同时修改钱数。takeSynWithdraw()方法实现同步互斥取钱的功能。当多个用户同时取钱时是按顺序执行的,也不会同时修改钱数。

  4. 从运行结果中可以看出:当没有使用同步互斥方法时,银行中钱总数为500,存入500再取钱时发现钱还是500,即后存入的钱没有入账。这是因为用户在存钱时另一用户对该账号进行取钱。当使用同步互斥方法后,用户向银行存入钱时,取钱的用户只能够等待,当存钱结束后,另一用户才能取钱,这样保证了钱数前后的一致。


评论关闭
评论 还能输入200
评论关闭
评论 还能输入200
  • 全部评论(0)
资料加载中...
已关注 , 取消