试水多线程-线程同步练习

首先小结一下释放锁的情况:

当前线程的同步方法、同步代码块执行结束。

当前线程在同步代码块、同步方法中遇到break、return终止了该代码块、该方法的继续执行。

当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致异常结束。

当前线程在同步代码块、同步方法中执行了线程对象的wait()方法,当前线程暂停,并释放锁。


同时注意不会释放锁的操作:

线程执行同步代码块或同步方法时,程序调用Thread.sleep()、Thread.yield()方法暂停当前线程的执行。

线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁(同步监视器)。(应尽量避免使用suspend()和resume()来控制线程)


小练习

银行有一个账户。有两个储户分别向同一个账户存3000元,每次存1000,存3次。每次存完打印账户余额。

问题:该程序是否有安全问题,如果有,如何解决?

【提示】

两个储户,涉及多线程。

同一个账户,共享数据。

(多线程不一定涉及线程安全,只有操作共享数据时才涉及线程安全。)

明确多线程运行代码中哪些语句是操作共享数据的。


第一印象,未考虑同步机制,出现线程安全问题,如下:

package com.ucar.quan.thread;

public class AccountTest {

	/**
	 * @param args
	 * 权兴权意-20160811
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Account account = new Account();
		Customer c1 = new Customer(account);
		Customer c2 = new Customer(account);
		c1.setName("甲");
		c2.setName("乙");
		c1.start();
		c2.start();
	}

}

class Account{
	double balance;//余额
	public Account(){
		
	}
	public void deposit(double amt){
		balance += amt;
		try {
			Thread.currentThread().sleep(10);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + ":" + balance);
	}
}

class Customer extends Thread{
	Account account;
	public Customer(Account account){
		this.account = account;
	}
	public void run(){
		for(int i = 0;i < 3;i++){
			account.deposit(1000);
		}
	}
}


注释掉休眠代码,减小问题发生几率,如下:

package com.ucar.quan.thread;

public class AccountTest {

	/**
	 * @param args
	 * 权兴权意-20160811
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Account account = new Account();
		Customer c1 = new Customer(account);
		Customer c2 = new Customer(account);
		c1.setName("甲");
		c2.setName("乙");
		c1.start();
		c2.start();
	}

}

class Account{
	double balance;//余额
	public Account(){
		
	}
	public void deposit(double amt){
		balance += amt;
//		try {
//			Thread.currentThread().sleep(10);
//		} catch (InterruptedException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		System.out.println(Thread.currentThread().getName() + ":" + balance);
	}
}

class Customer extends Thread{
	Account account;
	public Customer(Account account){
		this.account = account;
	}
	public void run(){
		for(int i = 0;i < 3;i++){
			account.deposit(1000);
		}
	}
}


使用同步方法,如下:

package com.ucar.quan.thread;

public class AccountTest {

	/**
	 * @param args
	 * 权兴权意-20160811
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Account account = new Account();
		Customer c1 = new Customer(account);
		Customer c2 = new Customer(account);
		c1.setName("甲");
		c2.setName("乙");
		c1.start();
		c2.start();
	}

}

class Account{
	double balance;//余额
	public Account(){
		
	}
	//synchronized 当前对象锁,确保唯一。
	public synchronized void deposit(double amt){
		balance += amt;
		try {
			Thread.currentThread().sleep(10);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + ":" + balance);
	}
}

class Customer extends Thread{
	Account account;
	public Customer(Account account){
		this.account = account;
	}
	public void run(){
		for(int i = 0;i < 3;i++){
			account.deposit(1000);
		}
	}
}











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值