为什么这个线程代码会挂起

pho*_*xis 4 java synchronization synchronized

在下面的代码中,当我执行producercon类时,有时执行卡住,看起来像死锁.但如果我进行get_flag () 同步则没有这样的问题.

我无法弄清楚怎么会有问题.该flag可真或假的所以只的一个producerconsumer将进入if声明.在其中一个进入后if,它将进入带有对象的监视器r(两者都使用相同的对象引用进行初始化).唯一的问题是,r对象被increment_decrement ()函数调用修改,并且同时get_flag ()读取标志,但即便如此,它也不会进入该if迭代,但它将if在下一次迭代时进入块,并且即使第一个线程没有离开监视器,它也会在那里等待它(在synchronized阻塞之前).

如果get_flag ()没有制作程序停止/悬挂的方式和原因synchronized

import java.io.*;

class resource
{
   private boolean res, flag;

   resource ()
   {
     flag=false;
   }

   boolean get_flag ()
   {
     return flag;
   }

   void increment_decrement (String s,boolean t)
   {
     res=t;
     flag=t;
      try 
      {
        System.out.print("\n"+s+":"+res);
        Thread.sleep(200);
      }
      catch(InterruptedException e)
      {
      }
   }
}

class producer implements Runnable
{
    resource r1;
    Thread t1;

    producer(resource r)
    {
      r1 = r;
      t1 = new Thread(this);
      t1.start();
    }

    public void run ()
    {  
      while (true)
      {
        if(r1.get_flag () == false)
        {
          synchronized(r1)
          {
            r1.increment_decrement("Producer",true);
          }
        }
      }
    }

   public void waitForThread () throws InterruptedException
   {
     t1.join ();
   }
}

class consumer implements Runnable
{
   resource r2;
   Thread t2;

   consumer(resource r)
   {
     r2 = r;
     t2 = new Thread (this);
     t2.start();
   }

   public void run()
   {
     while (true)
     {
       if(r2.get_flag () == true)
       {
         synchronized(r2)
         {
           r2.increment_decrement("Consumer",false);
         }
       }
     }
   }

   public void waitForThread () throws InterruptedException
   {
     t2.join ();
   }
} 

public class producercon
{
   public static void main(String args[])
   {
     try
     {
        System.out.print("PRESS CTRL+C TO TERMINATE\n");

        resource r = new resource();
        consumer c = new consumer(r);
        producer p = new producer(r);

        c.waitForThread ();
        p.waitForThread ();
     }
     catch(InterruptedException e)
     {
     }
   }
}
Run Code Online (Sandbox Code Playgroud)

Pet*_*rey 6

你对get_flag()的调用不是线程安全的,也不是volatile.这意味着在线程1的高速缓存中,它可以是真的,而在线程2的高速缓存中它可以是假的.

  • 是.使它"易变"也是如此.否则,该值可以在本地缓存,甚至可以放在寄存器中,而不是从内存中读取.你可以编写这段代码而不需要同步.;) (2认同)