且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

java多线程的等待唤醒机制及如何解决同步过程中的安全问题

更新时间:2022-01-29 12:22:31

/* 
class Person{
   String name;
   String sex;
   boolean flag = true;
   public void setPerson(String name, String sex){  
				 this.sex=sex;
				 this.name=name;   
   }
}
class Input implements Runnable{
   int x=0;
   Person p;
   Input(Person p){
      this.p=p;
   }
   public void run(){
       while(true){
		   if(x==1){
			  p.setPerson("hjz", "man");
		   }
		   else p.setPerson("哈哈哈", "女女女女");
		   x=(x+1)%2;
	   }
   } 
}

class Output implements Runnable{
   int x=0;
   Person p;
   Output(Person p){
      this.p=p;
   }
   public void run(){
       while(true){
	       System.out.println(p.name + "....." + p.sex);
	   }
   } 
} 
public class Test{
    public static void main(String[] args){
	     Person p = new Person();
		 new Thread(new Input(p)).start();
		 new Thread(new Output(p)).start();
	}
}
*/

/*
输出的结果:
哈哈哈.....man
hjz.....man
hjz.....man
哈哈哈.....man
hjz.....女女女女
*/

//线程安全隐患出现:首先考虑到是多线程操作了同一资源,所以要用同步!
/* 
class Person{
   String name;
   String sex;
   boolean flag = true;
   public void setPerson(String name, String sex){  
				 this.sex=sex;
				 this.name=name;   
   }
}

class Input implements Runnable{
   int x=0;
   Person p;
   Input(Person p){
      this.p=p;
   }
   public void run(){
       while(true){
	      synchronized(new Object()){
			   if(x==1){
				  p.setPerson("hjz", "man");
			   }
			   else p.setPerson("哈哈哈", "女女女女");
			   x=(x+1)%2;
		  }
	   }
   } 
}

class Output implements Runnable{
   int x=0;
   Person p;
   Output(Person p){
      this.p=p;
   }
   public void run(){
       while(true){
	       System.out.println(p.name + "....." + p.sex);
	   }
   } 
}
public class Test{
    public static void main(String[] args){
	     Person p = new Person();
		 new Thread(new Input(p)).start();
		 new Thread(new Output(p)).start();
	}
}
 */

//同步完成之后,发现还是出现安全隐患的情况,在考虑一下是否访问统一资源的多个线程用的是同一个锁!
//本例中的应将输入输出一起同步(注意输入输出不在同一个线程之中,输出线程不会获得 Person p对象的控制权!)
/*   class Input implements Runnable{
   int x=0;
   Person p;
   
   Input(Person p){
      this.p=p;
   }
   public void run(){
       while(true){
	      synchronized(p){
		       if(p.flag){
			     try{
					 p.wait();
				   }catch(InterruptedException e){
				   }
			   }
		       if(!p.flag){
				   if(x==1){
					  p.setPerson("hjz", "man");
				   }
				   else p.setPerson("哈哈哈", "女女女女");
				   x=(x+1)%2;
			   }
			   
			   p.flag=true;
			   p.notify();
			   
		  }
	   }
   } 
} */


//现在的代码是将同步放到函数里!真正开发过的时候就是这样实现,也就是我们多个线程同事操作一个类对象
//调用该类提供的对外方法,并将调用的方法进行同步!防止安全隐患!
class Person{
   String name;
   String sex;
   boolean flag = true;
   public void setPerson(String name, String sex){
       synchronized(this){
	     if(!flag){
		     try{
			    wait();
			 }catch(InterruptedException e){}
		 }
	     if(flag){
				 this.sex=sex;
				 try{
					Thread.sleep(100);
				 }catch(InterruptedException e){}
				 this.name=name;
	     }
		 flag=false;
		 notify();
	   }
   }
   
   public void outPerson(){
      synchronized(this){
	      if(flag){
		     try{
			     wait();
			 }catch(InterruptedException e){}
		  }
		  if(!flag){
		      System.out.println(name + "....." + sex);
		  }
		  flag=true;
		  notify();
	  }
   }
}

class Input implements Runnable{
   int x=0;
   Person p;
   
   Input(Person p){
      this.p=p;
   }
   public void run(){
       while(true){
				   if(x==1){
					  p.setPerson("hjz", "man");
				   }
				   else p.setPerson("哈哈哈", "女女女女");
				   x=(x+1)%2;
	   }
   } 
}

class Output implements Runnable{
   int x=0;
   Person p;
   Output(Person p){
      this.p=p;
   }
   public void run(){
       while(true){
	       p.outPerson();
	   }
   } 
}  


public class Test{
    public static void main(String[] args){
	     Person p = new Person();
		 new Thread(new Input(p)).start();
		 new Thread(new Output(p)).start();
	}
}