primefaces操作和multithreading

最近我正在阅读一个教程,因为我遇到了一个声明说…

“Java语言规范保证读取或写入变量是一个primefaces操作(除非变量是longdouble类型)。类型为longdouble操作变量只有在使用volatile关键字声明时才是primefaces的。”

AtomicIntegerAtomicLong提供像getAndDecrement()getAndIncrement()getAndSet()这样的方法。

我对上述陈述感到困惑。你能否澄清何时使用 AtomicIntegerAtomicLong类。

执行a = 28 (带有a int )是一个primefaces操作。 但是,执行a++不是primefaces操作,因为它需要读取a的值,增量和写入结果。 因此,如果您使用a++来实现线程安全计数器,您可以让两个线程同时读取该值(例如26),然后同时增加它并同时写入它,结果导致27,而不是28。

AtomicInteger通过提供您列出的primefaces操作来解决此问题。 在我的示例中,您将使用incrementAndGet() ,这将保证结束值为28而不是27。

primefaces意味着操作完成,没有任何可能发生的事情。 例如。 AtomicInteger上的getAndDecrement()保证变量同时返回和递减。

如果它不是primefaces操作,则存在值递减(例如从3到2),然后由另一个线程修改(例如,将其从2更改为5),然后返回为5的可能性。

如果需要读取变量并根据读取值写入结果,则需要AtomicInteger 。 例如, i++读取i (例如3 )并写入i+1 (例如4 )。 线程可能同时被中断,其他三个线程也会增加。 现在我们回来了, i实际上有值6但我们的线程仍然根据事先读取的内容写入4

AtomicInteger.getAndIncrement确保您不会被中断 ,因此总是正确递增。 此外,结果总是刷新到内存中 ,而非易失性i可能不会刷新到内存中。 在这种情况下,其他线程甚至可能看不到更改。

我认为这意味着长读和双读操作是primefaces的,写操作是primefaces的。 但是读/写不是primefaces的。

 volatile long num; num = num+1 

以上不是线程安全的。 读写是两个独立的操作。 每个都保证是primefaces的,但整个表达不是。

要使其线程安全,您需要使用AtomicLong并使用getAndIncrement函数。

您可以根据要处理的数字范围的上限/下限使用int或long。 请不要将长primefaces的非primefaces行为与AtomicLong混合。 无论你上面写的是什么都是正确的,但你可能会混合这两个概念。 在您进行“比较和设置”操作的情况下,AtomicXXX更有用。 例如,即使在multithreading环境中代码在primefaces上被修改/读取也是不正确的:

 int i =10 .. .. .. if(i == 10) i++; 

在multithreading环境中,两个线程可以primefaces方式访问此代码并更新i的值并使其处于一致状态。 所以通常你会处理这种情况“if(i == 10)i ++;” 与同步块。 但是,AtomicInteger类提供了实现此类function的API,而不使用速度较慢的同步块。 AtmoicLong API的情况也是如此

改变变量时需要操作的primefaces性。 做int a = 10; 是一个primefaces操作,但它不会给你带来问题。 给出操作的问题通常是变异的,如a++a = a + 2; 等等。

Java规范保证“读取”和“写入”是primefaces操作而不是它们的组合。 因此,“读取,添加1然后将结果写回”的操作根据规范不是primefaces的。 这样的操作称为复合操作,它们通常需要在我们的代码中使用它们的上下文。

primefaces类型有助于解决此问题。 在primefaces类型上使用incrementAndget()使得’读取,添加1然后将结果写回并读取新结果’在线程安全的上下文中的单个primefaces操作。

希望这可以帮助。 顺便说一句,你应该阅读这篇关于并发和线程基础知识的文章( http://walivi.wordpress.com/2013/08/24/concurrency-in-java-a-beginners-introduction/ )。 它很好地解释了这些东西。