我怎样才能解决这个“不完全同步”的问题?消费者生产者示例

发布于 2024-11-18 20:48:25 字数 3010 浏览 5 评论 0原文

我正在尝试熟悉 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,以便在添加数据时向消费者发出信号,但似乎它只在第一次起作用,之后生产者运行直到完成。我需要改变什么才能让它以消费者-生产者的方式运行,而不是以机器人工人的方式运行? :)

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

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? :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

脸赞 2024-11-25 20:48:25

您的消费者必须等待同时持有锁(如javadocs 用于方法状态)。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文