2013-11-03 133 views
-2

据我所知,写非阻塞(无锁)程序真的很困难。在使用基本构建模块(即CAS操作)编写Java应用程序时,仍然需要注意什么。写一个非阻塞程序

- 编辑 -

如果我有共同的资源,我不想要锁定的共享资源,而不是会想可能使用compareAndSet(expectedValue,valueToSet)指令在一个while循环,直到成功。在java中,我们有支持这个操作的AtomicXXX类。例如写非阻塞堆栈参考(Java并发实践)

什么所有的东西,我需要保持在我的脑海里,什么都测试场景可以有..

+4

您有任何具体问题吗? – SJuan76

+0

如果您希望非阻塞程序没有共享资源。 –

+0

如果我有共享资源,并且我不想锁定共享资源,而是希望在while循环中使用compareAndSet(expectedValue,valueToSet)指令,直到成功。在java中,我们有支持这个操作的AtomicXXX类。例如编写一个非阻塞堆栈参考(Java Concurrency in Practice) –

回答

3

的主要困难与锁相免费的编程是在架构层面。您需要以某种方式设计您的代码和算法,以免它们互相干扰数据。您需要在可以单独运行且独立运行的各个任务中“阻止”您的代码。然而,一旦你深入了解这些想法,你就开始想知道为什么你以前使用过这么多的阻止。

示例:Given是一个句子数组,并且您希望对每个单词中的单词进行计数,并且您希望以线程方式进行计算。

首先,您需要指出“阻塞点”,即线程可能发生冲突的位置。在这种情况下,数据源(数组)和数据输出是计数和结果的最终打印结果。因此,您需要找到一种方法,无需同步或锁定这些数据源。幸运的是,Java提供了Atomics类,它允许无阻塞地并发访问,并且允许进行大量的智能编码。

对于数组访问有两种选择:您可以使用AtomicInteger作为索引,并让其上的线程getAndIncremnt()获得其工作索引。如果你确实知道你有多少线程或者你的数据值有多长(这个提示:并非如此),这是非常有用的。

第二种选择是从一开始就为每个线程分配确定性索引,以确保没有线程干扰其他线程。如果你i.E.有4个线程和256个数据值,你可以以4的增量分配索引值。所以线程A得到0,4,8,...线程B获得1,5,9,等等。这确保了没有线程会与设计中的任何其他线程冲突。

最后的计数同样简单:首先让线程在内部计算单词,然后使用addAndGet()将总和添加到全局AtomicInteger中。

现在您只需要弄清楚何时打印该值。答案是“当最后一个线程完成时”。这可以再次完成 - 使用AtomicInteger作为计数器,并且让每个线程decrementAndGet()然后检查它们是否为0,这意味着它们是最后一个线程并需要打印结果。然后你可以使用一个Barrier类,它会阻塞,但在一个不再重要的地方,因为无论如何所有的工作都是在这个时候完成的。