1

我正在尝试熟悉 ReentrantLock 和 ConditionVariable 类。我实现了这个 Scala 代码(其中没有任何“Scala 特定”):

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
                    } finally { 
                        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)
    }
}

我试图在 ListBuffer 中生成 20 个元素,然后读取它们。我遗漏了一些东西,因为我的输出看起来像这样:

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

但我不知道是什么。我正在使用 ConditionVariable 以便在添加数据时向消费者发出信号,但它似乎只在第一次工作,然后生产者运行直到完成。我需要改变什么才能让它以消费者-生产者的方式运行,而不是以机器人工人的方式运行?:)

4

1 回答 1

4

您的消费者必须await 在持有锁的同时(作为方法状态 的javadocs )。

另外,你不应该使用tryLock,你应该只是使用lock. 仅当锁定获取失败时tryLock要执行其他操作时才使用。在您的情况下,如果锁定获取失败,您只需尝试再次获取它。

于 2011-07-08T12:32:36.327 回答