- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试学习 Scala,并发现它是一门很棒的语言。我学习"Beginning Scala"大卫波拉克。第三章中有一段代码,它说明了如何在没有同步块(synchronized block)的情况下编写多线程代码(这段代码是从书中复制的,可以从Apress site下载,我并没有在这里违反任何法律的意思):
import java.util.concurrent.atomic.{AtomicReference => AtomR, AtomicLong}import java.util.Randomimport scala.collection.immutable.TreeHashMapobject Multics { type MT = Map[String, Int] val info: AtomR[MT] = new AtomR(TreeHashMap.empty) val clashCnt = new AtomicLong def main(argv: Array[String]) { runThread { repeatEvery(1000) { println("Clash Count: "+clashCnt+" Total: "+ info.get.foldLeft(0)(_ + _._2)) } } for (i old + (name -> 0)} repeatEvery(ran.nextInt(100)) { doSet(info){old => old + (name -> (old(name) + 1))} cnt = cnt + 1 if (cnt != info.get()(name)) throw new Exception("Thread: "+name+" failed") } } } def runThread(f: => Unit) = (new Thread(new Runnable {def run(): Unit = f})).start def doSet[T](atom: AtomR[T])(update: T => T) { val old = atom.get if (atom.compareAndSet(old, update(old))) () else { clashCnt.incrementAndGet doSet(atom)(update) } } def repeatEvery(len: => Int)(body: => Unit): Unit = { try { while(true) { Thread.sleep(len) body } } catch { case e => e.printStackTrace; System.exit(1) } }}
据我了解,函数 doSet
中存在潜在的饥饿问题(不幸的线程可能总是冲突并导致 StackOverflowException)。我是对的吗?如果是这样,如何改进此代码以解决此问题?
最佳答案
首先,我认为您从书本示例中粘贴的代码中有很大一部分丢失了;这让你很难理解你的问题。
其次,确实可以递归调用 doSet() 多次,但在这种情况下不会发生 StackOverflowException,因为有一个优点:尾递归。 doSet() 在函数结束时被递归调用(在递归调用后不再进行处理)并且不能被覆盖(在对象内部定义),这使它有资格被优化为一个没有任何堆栈开销的循环。
在 2.8.0 中,有一个名为 @scala.annotation.tailrec 的注释,当用于 def 时,将确保 def 中的递归调用确实是尾递归的。
关于multithreading - 这段代码中是否存在潜在的饥饿问题,或者只是我?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1316080/
考虑以下服务器: public class TestServer { public static void main(String[] args) { String ksName = "/so
我正在研究工作队列处理器的设计,其中 QueueProcessor 从队列中检索命令模式对象并在新线程中执行它。 我正在尝试解决嵌套命令可能导致死锁的潜在队列锁定场景。 例如 一个 FooComman
通过使用 UNIX 管道进行进程同步,我们是否会陷入饥饿?例如: void pipesem_wait(struct pipesem *sem) { char onebyte = 'A';
这是使用 Scala 2.8 Actors。我有一个可以并行化的长时间运行的工作。它由大约 650,000 个工作单元组成。我将它分成 2600 个不同的独立子任务,并为每个子任务创建一个新角色: a
回答问题:Task.Yield - real usages?我建议使用 Task.Yield 允许池线程被其他任务重用。在这样的模式中: CancellationTokenSource cts;
我是一名优秀的程序员,十分优秀!