开发者

How can I fix this "not quite synchronized" consumer producer example

I am trying to familiarize myself with the ReentrantLock and ConditionVariable classes. I implemented this Scala code ( without anything "Scala specific" in it ):

object Conditioned {

    var pops        = 0
    var max         = 20

    abstract class NamedThread extends Thread {
        def myName = this.toString
    }

    class Producer(lock:Lock,condition:Condition,source:ListBuffer[Int]) extends NamedThread {
        override def run = {
            var number   = max
            var current  = 0
            while(current < number) 
            {
                if(lock.tryLock)
                {
                    try
                    {
                        current += 1
                        source  += current
                        println("producer added data:"+current)
                        condition.signal
                    } fin开发者_运维百科ally { 
                        lock.unlock 
                        Thread.sleep(100)
                    }
                }
            }

        }
    }
class Consumer(lock:Lock,condition:Condition,source:ListBuffer[Int]) extends NamedThread {
        override def run = {
            while(pops < max) {
                println("awaiting")
                while(source.isEmpty)
                    condition.await
                println("consumer try lock")
                if(lock.tryLock)
                {
                    try {
                            val data = source(source.size - 1)
                            source  -= data
                            println("consumer received data:"+data+" hello from:"+myName)
                            pops += 1
                    } finally { lock.unlock }
               } 
            }            
        }
    }

    def main(args:Array[String]) = {
        val lock        = new ReentrantLock
        val condition   = lock.newCondition
        var lb          = new collection.mutable.ListBuffer[Int]()
        val producer    = new Producer(lock,condition,lb)
        val consumer    = new Consumer(lock,condition,lb)
        val cons2       = new Consumer(lock,condition,lb)
        val threads     = Array(producer,consumer,cons2)
        threads.foreach(_.start)
        threads.foreach(_.join)
    }
}

I am trying to produce 20 elements in a ListBuffer, and then read them. I am missing something, because my output tends to look like this:

awaiting
consumer try lock
producer added data:1
awaiting
consumer try lock
consumer received data:1 hello from:Thread[Thread-51,5,trap.exit]
awaiting
awaiting
producer added data:2
producer added data:3
producer added data:4
producer added data:5
producer added data:6
producer added data:7
producer added data:8
producer added data:9
producer added data:10
producer added data:11
producer added data:12
producer added data:13
producer added data:14
producer added data:15
producer added data:16
producer added data:17
producer added data:18
producer added data:19
producer added data:20

But I don't know what. I am using a ConditionVariable so that I can signal the Consumer when data has been added, but it seems it only works the first time , and after that the producer runs until it finishes. What do I need to change to make it run in a consumer-producer fashion, and not in a robot worker kind of way? :)


Your consumer must await while holding the lock (as the javadocs for the method state).

also, you shouldn't be using tryLock, you should just be using lock. you only use tryLock if you are going to do something else if lock acquisition fails. in your case, if lock acquisition fails, you just try to acquire it again.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜