如何在开始编码之前处理并发

Tom*_*m R 16 java concurrency project-planning multithreading

我正在编写Java程序的过程中,我正处于调试并发问题的阶段,而不是我想要处理的问题.

我不得不问:在精神上设置你的程序时,你如何处理并发问题?在我的情况下,这是一个相对简单的游戏,但线程问题不断出现 - 任何快速修复几乎肯定会导致一个新的问题.

用非常笼统的术语来说,在决定我的应用程序应该如何"流动"而我的所有线程都没有结束时,我应该使用哪些技术?

ewe*_*nli 6

并发归结为管理共享状态.

"所有并发问题归结为协调对可变状态的访问.可变状态越少,确保线程安全越容易." - 实践中的Java并发

所以你必须问自己的问题是:

  • 什么是内在的我的应用程序将需要共享的数据?
  • 什么时候线程可以处理数据的快照,也就是说,它会在共享数据的克隆上暂时起作用?
  • 我是否可以识别已知模式并使用更高级别的抽象而不是低级锁定和线程协调,例如队列,执行程序等?
  • 考虑一个全局锁定方案,以避免死锁并获得一致的锁定

管理共享状态的最简单方法是序列化每个操作.然而,这种粗粒度的方法导致高锁争用和差的性能.管理并发可以看作是一种优化练习,您可以尝试减少争用.所以后续问题是:

  • 最简单的方法是什么?
  • 我可以做出哪些简单的选择来减少争用(可能是细粒度锁定)并提高性能而不会使解决方案过于复杂?
  • 什么时候我太精细了,也就是说,引入的复杂性不值得获得性能提升?

减少争用的许多方法依赖于在执行正确行为所必需的内容与减少争用的可行性之间的某种形式的权衡.

  • 我在哪里可以放松一些约束并接受有时候东西不会100%正确(例如柜台)?
  • 我是否可以乐观并且只有在发生并发修改时处理冲突(例如使用时间戳和重试逻辑 - 这就是TM所做的)?

请注意,我从未在游戏上工作,只在企业应用程序的服务器端部分工作.我可以想象它可能会完全不同.


whe*_*ies 5

我尽可能使用不可变数据结构.关于我唯一一次使用可变结构的时候,就像我需要一个可以节省大量工作的库一样.即使这样,我也尝试将该库封装在一个不可变的结构中.如果事情无法改变,那就不用担心了.

我应该补充一点,关于你未来的努力要记住的一些事情是STM和Actor模型.这两种并发方法都显示出非常好的进展.虽然每个都有一些开销,但取决于程序的性质可能不是问题.

编辑:

以下是您可以在下一个项目中使用的一些库的一些链接.有平分STM它顾名思义是STM实现为Java.然后是ActorFoundry,顾名思义是Java的Actor模型.但是,我不得不用Scala内置的Actor模型制作插件.


Eug*_*ota 5

阅读并发性,或者更好的是,如果你还在大学,那就读并发编程的研究生课程.请参阅Java教程:课程:并发.一本着名的Java并发书是Java Concurrency in Practice.Java有很多内置于框架中来处理并发问题,包括并发集合synchronized方法.

Java Concurrency in Practice http://ecx.images-amazon.com/images/I/51Hx%2Bg4Q6QL._BO2,204,203,200-76_AA240_SH20_OU01_.jpg

  • -1因为你没有回答任何海报问题,而只是告诉他他是多么无知. (4认同)

abc*_*abc 0

这取决于你的线程做什么。通常,程序有一个主线程来执行思考,工作线程来执行并行任务(计时器、在 GUI 上处理长时间计算等),但您的应用程序可能会有所不同 - 这取决于您的设计。你用线程做什么?您需要什么锁来保护共享数据结构?如果您使用多个锁,是否有一个锁定顺序来防止死锁?