免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 9332 | 回复: 5
打印 上一主题 下一主题

生产者与消费者模式的同步问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2004-07-01 11:38 |只看该作者 |倒序浏览
读教程时,遇到了生产者与消费者的例子,还有代码,运行后,出错,自己修改,正常,但是,却发生严重不同步问题。
如:生产者:a
    消费者:a
    生产者:b
    生产者:g
    生产者:p
    消费者:p
    消费者: p

请大家帮忙指定:谢谢!

代码如下:
class Producer extends Thread
{
   private Soup soup;
   private String alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   public Producer(Soup s)
   {
     soup=s;
   }
   public void run()
   {
     char c;
     for(int i=0;i<10;i++)
     {
        c=alphabet.charAt((int)(Math.random()*26));
        soup.add(c);
        System.out.println("Added  "+c+"  tothesoup.";
        try
         {
            sleep((int)(Math.random()*1000));
         }
        catch(InterruptedException e)
         {
         }
     }
   }
}

class Consumer extends Thread
{
  private Soup soup;
  public Consumer(Soup s)
  {
    soup=s;
  }
  public void run()
  {
    char c;
    for(int i=0;i<10;i++)
    {
      c=soup.eat();
      System.out.println("Atealetter: "+c);
      try
      {
        sleep((int)(Math.random()*1300));
      }
      catch(InterruptedException e)
      {
      }
    }
   }
}


class Soup
{
  private char buffer[]=new char[10];
  private int next=0;
  private boolean isFull=false;
  private boolean isEmpty=true;

  public synchronized char eat()
  {
   while(isEmpty==true)
   {
    try
    {
      wait();
    }
    catch(InterruptedException e)
    {
    }
   }
   if(next==0)
   {
    isEmpty=true;
   }
   isFull=false;
   notify();
   return(buffer[next-1]);
  }

  public synchronized void add(char c)
  {
    while(isFull==true)
    {
      try
      {
       wait();
      }
      catch(InterruptedException e)
      {
      }
    }
      if(next==10)
          {
              isFull=true;
      }
      buffer[next]=c;
      next++;
      isEmpty=false;
      notify();
  }
}

class Souptest
{
  public static void main(String args[])
  {
          Soup s=new Soup();
          Producer p1=new Producer(s);
          Consumer c1=new Consumer(s);
          p1.start();
          c1.start();
  }
}

论坛徽章:
0
2 [报告]
发表于 2004-07-01 13:21 |只看该作者

生产者与消费者模式的同步问题


  1. class Producer extends Thread {
  2.         private Soup soup;
  3.         private String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  4.         public Producer(Soup s) {
  5.                 soup = s;
  6.         }
  7.         public void run() {
  8.                 char c;
  9.                 for (int i = 0; i < 10; i++) {
  10.                         c = alphabet.charAt((int) (Math.random() * 26));
  11.                         soup.add(c);
  12.                         System.out.println("Added " + c + " tothesoup.");
  13.                         try {
  14.                                 sleep((int) (Math.random() * 1000));
  15.                         } catch (InterruptedException e) {
  16.                         }
  17.                 }
  18.         }
  19. }
  20. class Consumer extends Thread {
  21.         private Soup soup;
  22.         public Consumer(Soup s) {
  23.                 soup = s;
  24.         }
  25.         public void run() {
  26.                 char c;
  27.                 for (int i = 0; i < 10; i++) {
  28.                         c = soup.eat();
  29.                         System.out.println("Atealetter: " + c);
  30.                         try {
  31.                                 sleep((int) (Math.random() * 1300));
  32.                         } catch (InterruptedException e) {
  33.                         }
  34.                 }
  35.         }
  36. }
  37. class Soup {
  38.         private char buffer[] = new char[10];
  39.         private int next = 0;
  40.         private boolean isFull = false;
  41.         private boolean isEmpty = true;
  42.         public synchronized char eat() {
  43.                 while (isEmpty == true) {
  44.                         try {
  45.                                 wait();
  46.                         } catch (InterruptedException e) {
  47.                         }
  48.                 }
  49.                 if (next == 1) {
  50.                         isEmpty = true;
  51.                 }
  52.                 isFull = false;
  53.                 notify();
  54.                 return (buffer[--next]);
  55.         }
  56.         public synchronized void add(char c) {
  57.                 while (isFull == true) {
  58.                         try {
  59.                                 wait();
  60.                         } catch (InterruptedException e) {
  61.                         }
  62.                 }
  63.                 if (next == 10) {
  64.                         isFull = true;
  65.                 }
  66.                 buffer[next] = c;
  67.                 next++;
  68.                 isEmpty = false;
  69.                 notify();
  70.         }
  71. }
  72. public class SoupTest {
  73.         public static void main(String args[]) {
  74.                 Soup s = new Soup();
  75.                 Producer p1 = new Producer(s);
  76.                 Consumer c1 = new Consumer(s);
  77.                 p1.start();
  78.                 c1.start();
  79.         }
  80. }
复制代码

下次贴代码记得保持格式。你的哪个帖子完全没有缩进。

论坛徽章:
0
3 [报告]
发表于 2004-07-02 09:32 |只看该作者

生产者与消费者模式的同步问题

感谢朋友帮忙 真心谢谢
同时也记住了你的忠告 以后发代码一定会注意的

不过 由于本人太愚 还想问一下 为什么把

  1. if(next==0)
  2. {
  3. isEmpty=true;
  4. }
复制代码

改为

  1. if(next==1)
  2. {
  3. isEmpty=true;
  4. }
复制代码

呢?
又麻烦你了!

论坛徽章:
0
4 [报告]
发表于 2004-07-02 12:39 |只看该作者

生产者与消费者模式的同步问题

因为你是在consume之前就判断,也就是在取数据之前,这个时候,只要还剩一个字母,那么取了之后就会变成next=0,也就是empty了。如果你是在
  1. return (buffer[--next]);
复制代码
之后判断,那么就是
  1. if (next == 0) ...
复制代码

论坛徽章:
0
5 [报告]
发表于 2004-07-02 14:14 |只看该作者

生产者与消费者模式的同步问题

稍改了一下,我用了另外一种方法,采用双指针对 buffer 进行控制。


  1. class Producer extends Thread {
  2.         private Soup soup;
  3.         private String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  4.         public Producer(Soup s) {
  5.                 soup = s;
  6.         }
  7.         public void run() {

  8.                 for ( int i = 0; i <= 10; i++ )
  9.                 {
  10.                         try {
  11.                                 sleep( ( int )  ( Math.random() * 1000 ) );
  12.                                 char c = alphabet.charAt( ( int ) ( Math.random() * 26 ) );
  13.                                 soup.add( c );
  14.                                 System.out.println("Producer: add a letter " + c);
  15.                         }
  16.                         catch (InterruptedException exception) {
  17.                                 exception.printStackTrace();
  18.                         }
  19.                 }
  20.         }
  21. }

  22. class Consumer extends Thread {
  23.         private Soup soup;
  24.         public Consumer(Soup s) {
  25.                 soup = s;
  26.         }
  27.        
  28.         public void run() {
  29.                 for ( int i = 0; i <= 10; i++ )
  30.                 {
  31.                         try {
  32.                                 sleep( ( int ) ( Math.random() * 1000 ) );
  33.                                 char c = soup.eat();
  34.                                 System.out.println("Consumer: eat a letter " + c);
  35.                         }
  36.                         catch (InterruptedException exception) {
  37.                                 exception.printStackTrace();
  38.                         }
  39.                 }
  40.         }
  41. }

  42. class Soup {
  43.         private char buffer[] = new char[10];
  44.        
  45.         // nextFree points to the next free position int the buffer
  46.         // firstFull  points to the first full position in the buffer
  47.         private int nextFree = 0, firstFull = 0;       
  48.                
  49.         private boolean isEmpty = true;
  50.         private boolean isFull = false;

  51.         public synchronized char eat() {
  52.                 while ( isEmpty == true ) {
  53.                         try {
  54.                                 wait();
  55.                         }
  56.                         catch (InterruptedException exception) {
  57.                                 exception.printStackTrace();
  58.                         }
  59.                 }
  60.                 firstFull = ( firstFull + 1 ) % buffer.length;
  61.                 if ( firstFull == nextFree )
  62.                 {
  63.                         isEmpty = true; // buffer is  Empty
  64.                 }
  65.                 isFull = false; // buffe is not full, maybe empty or not
  66.                 notify();
  67.                 return ( buffer[ ( firstFull + buffer.length - 1 ) % buffer.length ] );
  68.         }

  69.         public synchronized void add(char c) {
  70.                 while ( isFull == true ) {
  71.                         try {
  72.                                 wait();
  73.                         }
  74.                         catch ( InterruptedException exception ) {
  75.                                 exception.printStackTrace();
  76.                         }
  77.                 }
  78.                 buffer[ nextFree ] = c;
  79.                 nextFree = ( nextFree + 1 ) % buffer.length;
  80.                 if ( ( ( nextFree + 1 ) % buffer.length )  == firstFull )
  81.                 {
  82.                         isFull = true; // buffer is full
  83.                 }
  84.                 isEmpty = false; // buffer is not empty, maybe full or not
  85.                 notify();
  86.         }
  87. }

  88. class SoupTester {
  89.         public static void main(String args[]) {
  90.                 Soup s = new Soup();
  91.                 Producer p1 = new Producer(s);
  92.                 Consumer c1 = new Consumer(s);
  93.                 p1.start();
  94.                 c1.start();
  95.         }
  96. }
复制代码
[/code]

论坛徽章:
0
6 [报告]
发表于 2004-07-14 14:03 |只看该作者

生产者与消费者模式的同步问题

前面的程序
try {  
        soup.add(c);    //////////应该放到try 里面,不然会死锁,
         System.out.println("Added " + c + " tothesoup.";
      
            sleep((int) (Math.random() * 1000));
         } catch (InterruptedException e) {
         }

private char buffer[] = new char[2]; ///10 改到2 就很容易看到了

我这样说对吗??
第二条的 eat 和add 放在 try 里就没事
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP