在我正在开发的应用程序中,多线程的使用让我左右为难。我有一个工作流,其中对象的状态发生了变化,这对于单线程操作没有任何问题。但是,为了提高性能,我计划使用多线程。
我的理解是,由于状态将在线程之间共享,因此每个线程在执行之前都必须获得状态上的锁,所以这不会违背多线程的目的吗?多线程似乎不会产生任何实际的并发性,所以它不会比单线程更好。
我的分析正确吗?如果我误解了,那么有人能澄清一下这个概念吗?
发布于 2017-05-06 05:41:12
简单的回答是:并发性很难。真正的并发,有多个并发编写器,真的很难。
您需要确定的是您的实际一致性保证需要是什么。是否每个读者都需要能够看到每一次写入,这是有保证的?然后,您将被迫以某种方式使用所有线程(例如,使用锁) --您的下一步工作应该是确保您在锁之外做尽可能多的工作,以便在尽可能短的时间内保持锁。
将锁保持最短时间的一种方法是使用。大多数无锁算法都基于原子比较和设置原语,比如java.util.concurrent.atomic包提供的那些原语。这些可能是非常高的性能,但设计一个成功的无锁算法可能是微妙的。一种简单的无锁算法是只构建一个新的(不可变的)状态对象,然后原子地使其成为“活动”状态,如果在此期间另一个编写器使不同的状态活动,则在循环中重试。(这种方法对于许多应用程序来说已经足够好了,但是如果您有太多的编写器,它就容易受到活锁的攻击。)
如果您可以在较宽松的一致性保证下过活,那么许多其他优化都是可能的。例如,您可以使用线程本地缓存,以便每个线程都能看到自己的数据视图,并且可以并行写入。然后,您需要处理数据过时或不一致的后果。这方面的大多数技术都在努力实现:写入可能不会立即对所有读者可见,但它们最终肯定会对所有读者可见。
这是一个活跃的研究领域,一个完整的答案可以填满一本书(真的,几本书!)。如果您在这一领域刚刚起步,我建议您阅读Goetz等人的,因为它对该主题提供了很好的介绍,并提供了许多关于如何成功构建并发系统的实用建议。
发布于 2017-05-06 05:39:24
您对多线程和并发限制的解释是正确的。由于状态必须由线程获取和控制,以便它们执行工作(并在不工作时等待),因此您实际上是将单个线程的工作拆分到多个线程中。
解决此问题的最好方法是调整程序设计以限制critical section的大小。正如我们在我的进程同步操作系统课程中学到的,
在任何给定时间只能执行一个临界区
术语Java 可能不会直接应用于并发,但它仍然说明了这一概念。
限制此临界区意味着什么?例如,假设您有一个管理单个银行帐户的程序(不切实际,但说明了我的观点)。如果帐户上的锁必须由线程获取才能更新余额,则基本选项是让单个线程在所有时间(无并发)更新余额。关键部分是整个程序。但是,假设还有其他要执行的逻辑,比如提醒其他银行余额更新。您可以仅在更新余额时要求锁定银行帐户状态,而不是在警告其他银行时,减小临界区的大小,并允许其他线程通过在一个线程更新余额时警告其他银行来执行工作。
如果这一点不清楚,请发表评论。您似乎已经了解了并发性的限制,但希望这将揭示实现并发性的可能步骤。
发布于 2017-05-06 05:40:35
您的需求并不完全清楚,但您可以很好地猜测多线程可能具有的限制。
运行并行线程可以判断一些“相对自主”的任务是否可以由不同的线程或线程组并发执行。
如果您的场景是这样的:您启动了5个线程,最后只有一个线程是活动的,而其他线程正在等待锁定资源,那么使用多线程是没有意义的,甚至可能会因为cpu上下文切换而引入开销。
我认为在您的用例中,多线程可以用于:
https://stackoverflow.com/questions/43813956
复制相似问题