Как я могу исправить этот пример "не совсем синхронизированного" - PullRequest
1 голос
/ 08 июля 2011

Я пытаюсь ознакомиться с классами 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)
    }
}

Я пытаюсь создать 20 элементов в ListBuffer, а затем прочитать их. Я что-то упустил, потому что мой вывод выглядит примерно так:

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, чтобы я мог сигнализировать Потребителю, когда данные были добавлены, но кажется, что это работает только в первый раз, и после этого производитель работает, пока не закончится. Что мне нужно изменить, чтобы заставить его работать в режиме потребитель-производитель, а не в стиле робота? :)

1 Ответ

4 голосов
/ 08 июля 2011

Ваш потребитель должен await , удерживая блокировку (как javadocs для состояния метода).

также, вы не должны использовать tryLock, вы должны просто использовать lock. вы используете tryLock только если вы собираетесь сделать что-то еще , если получение блокировки не удалось. в вашем случае, если получение блокировки не удается, вы просто пытаетесь получить его снова.

...