由小程序来看多线程的运行问题

本文通过一个具体的例子探讨了多线程环境下资源管理和线程间通信的问题。详细介绍了如何使用同步锁解决线程冲突,并展示了如何利用wait和notify方法实现线程间的正确交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先先看一段小例子:

描述这样一个场景: 


多线程问题就被简化为一个资源库,有的线程往里添加资源,有的线程往外输出资源。



描述该部分的代码示例:

/*
*线程间通讯问题
*其实就是多线程操作同一个资源
*但是操作的动作不同
*/

class Res
{
	String name;           //定义一个资源库  由Input往里面添加资源,Output往外面出售资源
	String sex;
}
class Input implements Runnable
{ 
	private Res r;
	Input(Res r)                 //初始化一个资源库
	{	
		this.r=r;
	}
	public void run()
	{
		int n=0;
		while(true)
		{
			if(n==0)
			{
				r.name="mike";                    //插入资源
				r.sex="man";
			}
			else{
				r.name="丽丽";
				r.sex="女";
			}
			n=(n+1)%2;
		}
	}

}
class Output implements Runnable
{
	private Res r;
	Output(Res r)						 //初始化一个资源库
	{	
		this.r=r;
	}
	public void run()
	{
		while (true)
		{
			System.out.println(r.name+"    "+r.sex);           //输出资源库
		}
	}

}



class  test
{
	public static void main(String[] args) 
	{
		//System.out.println("Hello World!");
		Res r=new Res();
		Input in=new Input(r);
		Output out=new Output(r);

		Thread t1=new Thread(in);
		Thread t2=new Thread(out);
		t1.start();
		t2.start();						//资源的启动
	}
}


运行结果截图:



问题分析:

先不说while是个死循环,那是为了看到运行结果写的。该多线程描述就是对于一个资源库进行存资源,取资源的过程。出现问题的原因就是线程权限抢过来抢过去的问题,当存获取到权限刚执行完mike后还没来得及存man就被输出抢走占据cpu的权限。

解决方法:

用同步线程锁。


再看完善后的代码:


/*
*线程间通讯问题
*其实就是多线程操作同一个资源
*但是操作的动作不同
*/

/*
 * wait()
 * notify()
 * notifyAll()
 * 都是用在同步中,因为要对持有监视器(锁)的线程的操作
 * 因为只有同步才具有锁
 * 为什么这些操作线程的方法要定义Object类中呢?
 * 因为这些方法在操作同步线程时,都必须标示他们操作线程只有的锁
 * 只有同一个锁上的被等待线程,才能被同一个锁上的notify()唤醒,不可以对不同锁上的唤醒
 * 
 * 也就是说等待唤醒必须同一个锁,而锁可以是任意对象,所以可以被任意对象调用的定义方法Object类中。
 * 
 * 
 */

class Res
{
	private String name;           //定义一个资源库  由Input往里面添加资源,Output往外面出售资源
	private String sex;
	private boolean flag=false;
	
	public synchronized void set(String name,String sex)
	{
		if(flag)
			try{
				this.wait();  //执行就放弃了执行的资格
			}catch (Exception e) {
				// TODO: handle exception
			}
		this.name=name;
		this.sex=sex;
		flag=true;
		this.notify();//唤醒该对象正在等待该对象的线程
		
	}
	public synchronized void out()
	{
		if(!flag)
			try{
				this.wait();  //执行就放弃了执行的资格
			}catch (Exception e) {
				// TODO: handle exception
			}
		System.out.println(name+"........."+sex);
		flag=false;
		this.notify();
	}
}

class Input implements Runnable
{ 
	private Res r;
	Input(Res r)                //初始化一个资源库
	{	
		this.r=r;
	}
	public void run()
	{
		int n=0,m=0;
		while(m<100)
		{			
				if(n==0)
				{
					r.set("mike","man");//插入资源
				}
				else{
					r.set("丽丽","女"); 
				}
				n=(n+1)%2;
				m++;
				
			
		}
	}

}
class Output implements Runnable
{
	private Res r;
	Output(Res r)						 //初始化资源
	{	
		this.r=r;
	}
	public void run()
	{
		int i=0;
		while (i<100)
		{
		
					r.out();//调用out输出资源
					i++;
			          
		}
	}

}



class  test
{
	public static void main(String[] args) 
	{
		//System.out.println("Hello World!");
		Res r=new Res();
		new Thread(new Input(r)).start();
		new Thread(new Output(r)).start();
		
		/*
		Input in=new Input(r);
		Output out=new Output(r);

		Thread t1=new Thread(in);
		Thread t2=new Thread(out);
		t1.start();//启动线程
		t2.start();	
		*/					
	}
}

输出结果:



心得:

Synchronized是对当前的实例进行加锁,要注意是“当前实例”,也就是说,假如你有两个实例化对象,那么可以同时访问这两个实例里面的Synchronized块。但是,当访问一个实例里面的一个Synchronized块时,其余的synchronized是不可同时访问的,原因是整个实例都被加了锁。

另外注意wait()和notify():如果条件不满足,则等待。当条件满足时,等待该条件的线程将被唤醒。一般用在synchronized机制中,用在一个对象中,描述对一个对象的控制。



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值