线程同步

线程同步:

 一、线程同步:

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

 

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

   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);
		
	}
}

  

 三、运行结果:

   
 

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

 

 四、处理

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

 

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

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

 代码改善:

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

 运行结果:

 
 
 

 解决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;
		
	}
	
}

 运行结果:

 
 
 

五、总结.

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

 

基于51单片机,实现对直流电机的调速、测速以及正反转控制。项目包含完整的仿真文件、源程序、原理图和PCB设计文件,适合学习和实践51单片机在电机控制方面的应用。 功能特点 调速控制:通过按键调整PWM占空比,实现电机的速度调节。 测速功能:采用霍尔传感器非接触式测速,实时显示电机转速。 正反转控制:通过按键切换电机的正转和反转状态。 LCD显示:使用LCD1602液晶显示屏,显示当前的转速和PWM占空比。 硬件组成 主控制器:STC89C51/52单片机(与AT89S51/52、AT89C51/52通用)。 测速传感器:霍尔传感器,用于非接触式测速。 显示模块:LCD1602液晶显示屏,显示转速和占空比。 电机驱动:采用双H桥电路,控制电机的正反转和调速。 软件设计 编程语言:C语言。 开发环境:Keil uVision。 仿真工具:Proteus。 使用说明 液晶屏显示: 第一行显示电机转速(单位:转/分)。 第二行显示PWM占空比(0~100%)。 按键功能: 1键:加速键,短按占空比加1,长按连续加。 2键:减速键,短按占空比减1,长按连续减。 3键:反转切换键,按下后电机反转。 4键:正转切换键,按下后电机正转。 5键:开始暂停键,按一下开始,再按一下暂停。 注意事项 磁铁和霍尔元件的距离应保持在2mm左右,过近可能会在电机转动时碰到霍尔元件,过远则可能导致霍尔元件无法检测到磁铁。 资源文件 仿真文件:Proteus仿真文件,用于模拟电机控制系统的运行。 源程序:Keil uVision项目文件,包含完整的C语言源代码。 原理图:电路设计原理图,详细展示了各模块的连接方式。 PCB设计:PCB布局文件,可用于实际电路板的制作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值