免责声明:我对CSP的理论背景知之甚少。
自从我读到它之后,我倾向于构建我的多线程“CSP-like”的大多数,这意味着我有线程在BlockingQueue
上等待作业。
这非常有效,简化了我对线程的思考。
synchronized
阻止我在表现方面更好的情况吗?答案 0 :(得分:1)
这种方法的缺点是什么?
并不多。队列可能需要比无竞争锁更多的开销 - 队列类在内部需要某种锁来保护它免受多次访问。与一般的线程池和排队通信的优点相比,一些额外的开销并没有太多困扰。
使用同步块更好吗?
好吧,如果你绝对必须在线程之间共享可变数据:(
是否存在某种性能影响,
不是所有人都会注意到的。实际上,未就绪的线程是内核中某个容器中的额外指针条目(例如,属于信号量的队列)。不值得打扰。
答案 1 :(得分:1)
这是设计代码体系结构以防止线程问题发生的可能方法,但这不是唯一的,有时不是最好的。
首先,你显然需要有一系列可以拆分并放入这样一个队列的任务,但是如果你必须计算一个但非常紧张的公式的结果,情况并非总是这样。只是不能拆开使用多线程。
如果手头的任务太小,那么创建任务并将其添加到列表中的问题已经比任务本身更昂贵了。示例:您需要将许多对象上的布尔标志设置为true。可分割,但操作本身并不复杂,无法证明每个布尔值的新Runnable。
您当然可以提出解决方案来解决这个问题,例如,通过让每个线程每次执行设置100个标记,第二个示例可以合理地用于您的方法,但这只是一个解决方法。
您应该将线程化的想法想象成它们:帮助您解决问题的工具。所以使用它们的并发框架和模式都只是一个大工具箱,但每次你手头有一个任务,你需要从那个盒子中选择一个工具,因为最后用锤子拧一个螺丝是可能,但可能不是最佳解决方案。
我建议更熟悉这些工具,每次遇到涉及线程的问题时:通过工具,选择您认为最合适的工具,然后进行实验,直到您对此特定工具感到满意为止最适合特定任务。毕竟原型是盒子里的另一个工具。 ;)
答案 2 :(得分:0)
每当两个或多个线程访问可变数据时,您需要同步块,Atomics和volatile。将此保持在最低限度,不会影响您的设计。有许多Java API类可以为您处理,例如BlockingQueue。
但是,如果您的问题/解决方案的性质不合适,可能会遇到麻烦。如果您的线程尝试同时读取/修改相同的数据,您会发现大多数线程都在等待锁定,而且大多数内核都无法执行任何操作。为了缩短响应时间,你必须让更多的线程运行,也许忘记了队列并让它们全部运行。
这成了一种折衷。更多的线程会占用大量的CPU时间,如果你有它的话,这是可以的,并且可以缩短响应时间。对于给定的工作量,较少的线程使用较少的CPU时间(但是您将如何节省成本?)并减慢响应时间。
关键点:在这种情况下,您需要一个批次运行线程,而不是核心,以保持所有核心忙碌。
这种编程(多线程而不是并行)很难和(不可复制的)容易出错,所以如果可以在开始考虑性能之前就想避免它。此外,如果您拥有超过2个免费核心,它只会有明显的帮助。它只需要某些问题。但是你确实要求下行,并且可能知道这是在那里。