经典的生产与消费线程同步问题

转载 2012年03月26日 10:44:02

java code:

class SynStack 
{
    private char[] data = new char[6];
    private int cnt = 0; //表示数组有效元素的个数
    
    public synchronized void push(char ch)
    {
        while (cnt == data.length)
        {
            try
            {
                this.wait();
            }
            catch (Exception e)
            {
            }
        }
        this.notify(); 
        
        data[cnt] = ch;
        ++cnt;
        System.out.printf("生产线程正在生产第%d个产品,该产品是: %c\n", cnt, ch);
    }
    
    public synchronized char pop()
    {
        char ch;
        
        while (cnt == 0)
        {
            try
            {
                this.wait();
            }
            catch (Exception e)
            {
            }
        }
        this.notify();
        ch = data[cnt-1];
        
        System.out.printf("消费线程正在消费第%d个产品,该产品是: %c\n", cnt, ch);
        
        --cnt;
        return ch;        
    }    
}


class Producer implements Runnable
{
    private SynStack ss = null;
    
    public Producer(SynStack ss)
    {
        this.ss = ss;
    }
    
    public void run() 
    {
        char ch;
        
        for (int i=0; i<20; ++i)
        {        
            ch = (char)('a'+i);
            ss.push(ch);
        }
    }
}


class Consumer implements Runnable
{
    private SynStack ss = null;
    
    public Consumer(SynStack ss)
    {
        this.ss = ss;
    }
    
    public void run()
    {
        for (int i=0; i<20; ++i)
        {
            try{
            Thread.sleep(100);
            }
            catch (Exception e){            
            }
            ss.pop();
        }
    }
}




public class TestPC
{
    public static void main(String[] args)
    {
        SynStack ss = new SynStack();
        Producer p = new Producer(ss);
        Consumer c = new Consumer(ss);
        Thread t1 = new Thread(p);
        t1.start();
                
        Thread t2 = new Thread(c);
        t2.start();
    }
}


我的问题是, push 和 pop 中的 while 可不可以用 if 代替,如果不可以是不是这样理解的:假设是生产被暂停了,转到消费,当生产被唤醒,下次转到生产时是不是从被暂停的地方开始,就是 this.wait() 那里开始,还是重新执行 run(),从头开始,如果是这样的话,好像 while 就不能 if 替代了。不知道我的理解对不对?


回复1:

用while是为了防止你的pop,push不是被对方唤醒的。因为你的synchronized 用的是当前对象,有可能它在其它地方也作为一个锁。
所以,你用notify也不对,应该用notifyAll。

回复2:

线程唤醒后是从wait()后边的语句执行。一楼说的有道理“用while是为了防止你的pop,push不是被对方唤醒的。”。
我认为,就楼主的程序,没必要用notifyAll(). 也可以用if.

回复3:

这个,我仔细想了想,从逻辑上说这个应该不能用if代替while,因为当被唤醒后,理论上应该再次判断是否栈是满的(或是空的),这个貌似if只判断一次,虽然在这里好像没什么区别,但逻辑上应该是这样的,就像 1楼 说的可能是被别的什么唤醒的,那么很显然就会有问题了。不知道 1楼 的是不是这个意思。至于,notify和notifyAll的话,在这个问题中,线程只有两个,所以,用哪个应该都没有区别把.

回复4:

不能用if,用while用if的话,那个线程被唤醒,马上就会去运行,不会再次检测了,而且lz的try catch 最好写在while循环之外,因为那样即使发生异常,程序还会在循环中运行。

回复5:

“用if的话,那个线程被唤醒,马上就会去运行,不会再次检测了”
这个应该不可能。 线程唤醒后,会从"Object's wait pool" 进入"Object's lock pool",
那个执行了"notify()的线程还在synchronized 方法里,还继续占着锁不释放。直到它执行完,才会释放锁,被唤醒线程才有机会执行。不会象楼上说的 “马上去执行”。

回复6:

学习了,确实觉得是为了在被其他的线程唤醒的时候,能再度wait。且使用notify也确实不对,如果notify了一个线程,而这个线程发现不是自己想要的数据唤醒的自己,所以就会wait,这样就浪费了一次“唤醒”的机会。最后将会死锁。

所以用notifyAll是有必要的。

相关文章推荐

java线程同步----生产消费

上次学习了java线程的同步,在线程的使用过程中需要注意数据的操作问题。说道这个,就会想到在学习同步时的经典示例---生产者消费者             这样,首先的看看API: &#...

经典线程同步互斥问题在windows下的各种解法

这篇文章记录是来源于Windows多线程系列的学习笔记,表为原创,实为转载文章,只是为了让自己学的明白,稍微整理了下而已,在此向“MoreWindows”大神致敬!问题所在题目要求主线程启动10个子线...

经典线程同步问题(三)

问题: 有四个线程1、2、3、4。线程1的功能就是输出1,线程2的功能就是输出2,以此类推.........现在有四个文件ABCD。初始都为空。现要让四个文件呈如下格式: A:1 2 3 4 1 ...

经典线程同步问题(生产者&消费者)--Java实现

====================================================== 注:本文源代码点此下载 =============================...

经典线程同步问题(生产者&消费者)

生产者-消费者(producer-consumer)问题是一个著名的线程同步问题。它描述的是:有一群生产者线程在生产产品,并将这些产品提供给消费者线程去消费。 为使生产者与消费者之间能够并发执行,在两...

线程同步问题

Java中多线程的多生产多消费问题的解决方案

/*创建线程的第二种方式1、实现Runnable接口2、覆盖run方法3、通过Thread类创建线程对象4、将Runnable接口的子类对象作为实参传递给Thread类中的构造函数5、调用start方...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)