首页 > 编程语言 > 详细

线程同步

时间:2015-05-31 02:04:12      阅读:360      评论:0      收藏:0      [点我收藏+]

线程同步:

?一、线程同步:

??线程的同步,就是要保证线程在执行某个计算时,需要保证相关的数据在这个计算过程中只能被一个线程访问,即保证访问数据的原子性---就像一个坐位,只能同时被一个人(线程)所使用。

?

?二、举例,以在银行取钱为例子:

? ?1.创建账户:

?

package 线程同步;
/**
 * 银行账户对象
 * @author Administrator
 *
 */
public class Account {

	private int total=0;
	//构造有指定金额的银行账户
	public Account(int save){
		this.total = save;
	}
	
	public String toString(){
		
		return "账户余额:"+total;
	}
	
	//取钱的
	private void disSave(int count){
		try{
			Thread.sleep(1000);
		}catch(Exception ed){
				
		}
		
		total=total-count;
		
	}
	
	//从账户上提取现金的调用方法
	public   int getCash(int count){
		//金额不足
		if (total<count) {
			return -1;
		}
		
		//从账户上减去提取金额
		disSave(count);
		
		return count;
		
	}
	
}

?

?

? 2.取钱线程:

package 线程同步;

public class GetCashThread extends Thread {

	private  Account ac;//操作账户
	private  String flag;//取钱方式
	private  int disCount;//取现金额
	
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		//super.run();
		//在这里取钱
		
		//synchronized (ac) {
			
			int cash=ac.getCash(disCount);
			System.out.println(flag+"取了:"+cash);
		//}
		
	}




	public GetCashThread(Account ac,String flag,int disCount){
		
		this.ac = ac;
		this.flag = flag;
		this.disCount = disCount;
		
	}
	
}

??

?

? ?3.Main类:

package 线程同步;

public class DriverBank {

	public static void main(String[] args) {
		//创建一个账号:
		Account ac = new Account(5000);
		
		//从ATM取
		GetCashThread atmGet = new GetCashThread(ac, "ATM取款", 2500);
		
		//从柜台取
		GetCashThread counterGet = new GetCashThread(ac, "从柜台取款", 2600);
		
		//启动取款线程
		atmGet.start();
		counterGet.start();
		
		//主线程暂停,等到前面两个取款线程完成,打印出账户余额
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(ac);
		
	}
}

??

?三、运行结果:

? ?bubuko.com,布布扣
?

? ? ?账户共有5000,可是分别取到2500,2600,余额是-100,这就是线程不同步,所造成的结果.ATM的线程取钱时,柜台取钱进入取钱,此时的ATM的线程还未结算完,导致账户上还是5000,

?

?四、处理

? 解决原理:避免多个线程同时操作某一个对象的数据,就要让多线程操作对象的数据时候有一个先后顺序,一个操作完成另一个线程在操作的。

?

? ? 解决1---使用synchronized关键字

? 这个关键字可以放在一个方法前,表示这个方法同时只能被一个线程访问,或通过锁定某个对象放在代码块前,表示其限定的代码块只能同时被一个线程防问。

?代码改善:

		synchronized (ac) {
			int cash=ac.getCash(disCount);
			System.out.println(flag+"取了:"+cash);
		}
		

?运行结果:

?
?bubuko.com,布布扣
?

?解决2--使用java.util.concurrent

?这个包中有许多对并发编程有良好支持的类,其中新增了一个java.util.concurrent.locks.Lock接口,这是一个对象的接口,它的多个实现的子类可用来支持线程同步时灵活的锁机制

?代码改善:

package 线程同步;
import java.util.concurrent.locks.*;
import java.util.concurrent.locks.ReentrantLock;

public class GetCashThread extends Thread {

	private  Account ac;//操作账户
	private  String flag;//取钱方式
	private  int disCount;//取现金额
	
	//定义一个同步锁
	private static Lock myLock = new ReentrantLock();
	
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		//super.run();
		//在这里取钱
		
			
		try{
			myLock.lock();// 仅有一个线程可同时执行此段代码
			int cash=ac.getCash(disCount);
			System.out.println(flag+"取了:"+cash);
		}finally{
			myLock.unlock();
		}
			

	}




	public GetCashThread(Account ac,String flag,int disCount){
		
		this.ac = ac;
		this.flag = flag;
		this.disCount = disCount;
		
	}
	
}

?运行结果:

?
?bubuko.com,布布扣
?

五、总结.

? 避免多线程同时操作某一对象的数据,要给线程加上执行顺序.

?

线程同步

原文:http://cb123456.iteye.com/blog/2215626

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!