A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

在多线程技术中,如果两个(或多个)线程对共同数据资源做不同操作,为了保持数据同步性,要调用线程的等待和唤醒操作。如果把wait()方法用在synchronized外面则会出现数据错误。请问是为什么呢?
  1. /*
  2.         线程间的通信,两个线程对同一个数据做不同操作的安全问题
  3. */
  4. class src
  5. {
  6.         public boolean flag=true;
  7.         String name;
  8.         String sex;
  9. }
  10. class Input implements Runnable
  11. {
  12.         private src s;
  13.         public Input(src s)
  14.         {
  15.                 this.s=s;
  16.         }
  17.         public void run()
  18.         {
  19.                 int x=0;
  20.                 while(true)
  21.                 {  
  22.                        
  23.                         synchronized(s)
  24.                         {
  25.                                 if(!s.flag)
  26.                                         try
  27.                                                 {
  28.                                                         s.wait();
  29.                                                 }
  30.                                                 catch (Exception e)
  31.                                                 {
  32.                                                 }
  33.                                 if(x==0)
  34.                                 {
  35.                                         s.name="张三";
  36.                                         s.sex="男";
  37.                                         x=1;
  38.                                 }
  39.                                 else
  40.                                 {               
  41.                                         s.name="李思";
  42.                                         s.sex="女";
  43.                                         x=0;
  44.                                 }
  45.                                 s.flag=false;
  46.                                 s.notify();
  47.                         }
  48.                 }
  49.         }
  50.                
  51. }
  52. class Output implements Runnable
  53. {
  54.         private src s;
  55.         public Output(src s)
  56.         {
  57.                 this.s=s;
  58.         }
  59.         public void run()
  60.         {
  61.                 while(true)
  62.                 {
  63.                        
  64.                         synchronized(s)
  65.                         {
  66.                                 if(s.flag)
  67.                                         try
  68.                                         {
  69.                                                 s.wait();
  70.                                         }
  71.                                         catch (Exception e)
  72.                                         {
  73.                                         }
  74.                                 System.out.println("姓名:"+s.name+"……性别:"+s.sex);
  75.                                 s.flag=true;
  76.                                 s.notify();
  77.                         }
  78.                 }
  79.                
  80.         }
  81. }
  82. class  InputOutputDemo
  83. {
  84.         public static void main(String[] args)
  85.         {
  86.                 src s=new src();
  87.                 Input in=new Input(s);
  88.                 Output out=new Output(s);
  89.                 Thread t1=new Thread(in);
  90.                 Thread t2=new Thread(out);
  91.                 t1.start();
  92.                 t2.start();
  93.         }
  94. }
复制代码
如果把代码改成这样:
  1. /*
  2.         线程间的通信,两个线程对同一个数据做不同操作的安全问题
  3. */
  4. class src
  5. {
  6.         public boolean flag=true;
  7.         String name;
  8.         String sex;
  9. }
  10. class Input implements Runnable
  11. {
  12.         private src s;
  13.         public Input(src s)
  14.         {
  15.                 this.s=s;
  16.         }
  17.         public void run()
  18.         {
  19.                 int x=0;
  20.                 while(true)
  21.                 {  
  22.                         if(!s.flag)
  23.                                         try
  24.                                                 {
  25.                                                         s.wait();
  26.                                                 }
  27.                                                 catch (Exception e)
  28.                                                 {
  29.                                                 }
  30.                         synchronized(s)
  31.                         {
  32.                                
  33.                                 if(x==0)
  34.                                 {
  35.                                         s.name="张三";
  36.                                         s.sex="男";
  37.                                         x=1;
  38.                                 }
  39.                                 else
  40.                                 {               
  41.                                         s.name="李思";
  42.                                         s.sex="女";
  43.                                         x=0;
  44.                                 }
  45.                                 s.flag=false;
  46.                                 s.notify();
  47.                         }
  48.                 }
  49.         }
  50.                
  51. }
  52. class Output implements Runnable
  53. {
  54.         private src s;
  55.         public Output(src s)
  56.         {
  57.                 this.s=s;
  58.         }
  59.         public void run()
  60.         {
  61.                 while(true)
  62.                 {
  63.                         if(s.flag)
  64.                                         try
  65.                                         {
  66.                                                 s.wait();
  67.                                         }
  68.                                         catch (Exception e)
  69.                                         {
  70.                                         }
  71.                         synchronized(s)
  72.                         {
  73.                                
  74.                                 System.out.println("姓名:"+s.name+"……性别:"+s.sex);
  75.                                 s.flag=true;
  76.                                 s.notify();
  77.                         }
  78.                 }
  79.                
  80.         }
  81. }
  82. class  InputOutputDemo
  83. {
  84.         public static void main(String[] args)
  85.         {
  86.                 src s=new src();
  87.                 Input in=new Input(s);
  88.                 Output out=new Output(s);
  89.                 Thread t1=new Thread(in);
  90.                 Thread t2=new Thread(out);
  91.                 t1.start();
  92.                 t2.start();
  93.         }
  94. }
复制代码
这样会出现数据存取错误。请问原因?

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马