有没有理由不总是使用AtomicInteger作为数据成员?

在像Android这样的multithreading环境中,一个简单的int变量可能被多个线程操纵,在哪种情况下仍然有理由使用int作为数据成员?

作为局部变量的int ,仅限于具有独占访问权限的方法的范围(因此开始和完成修改它总是在同一个线程中),在性能方面完全有意义。

但作为数据成员,即使由访问器包装,它也可能遇到众所周知的并发交错修改问题。

所以看起来“玩得安全”可以全面使用AtomicInteger 。 但这似乎非常低效。

你能带一个线程安全的int数据成员用法的例子吗?

有没有理由不总是使用AtomicInteger作为数据成员?

是的,有充分的理由总是使用AtomicIntegerAtomicInteger可以至少慢一个数量级(可能更多),因为volatile构造比一个局部int和其他Unsafe构造用于设置/获取底层int值。 volatile表示每次访问AtomicInteger 都会跨越内存屏障,这会导致有问题的处理器上的缓存内存冲洗。

此外,仅仅因为您将所有字段设置为AtomicInteger并不能在访问多个字段时保护您免受竞争条件的影响。 对于何时使用volatilesynchronizedAtomic*类做出正确的决定没有任何替代品。

例如,如果您希望在线程程序中以可靠的方式访问类中的两个字段,那么您将执行以下操作:

 synchronized (someObject) { someObject.count++; someObject.total += someObject.count; } 

如果这两个成员都使用AtomicInteger那么您将访问volatile两次,因此跨越2个内存屏障而不是1。此外,分配比AtomicIntegerUnsafe操作更快。 此外,由于两个操作的数据竞争条件(与上面的synchronized块相反),您可能无法获得正确的total

你能带一个线程安全的int数据成员用法的例子吗?

除了将其标记为volatile或使用AtomicInteger之外,没有任何机制可用于线程安全的int数据成员。 没有神奇的方法可以在所有字段上绘制线程安全性。 如果有,那么线程编程将很容易。 挑战在于找到放置synchronized块的正确位置。 找到应标记为volatile的正确字段。 找到合适的地方使用AtomicInteger和朋友。

如果你有一个有效的不可变的东西,你可以逃避不以计算为代价来确保同步。 一个例子是hashCode

 int hash = 0; public int hashCode(){ if(hash == 0){ hash = calculateHashCode(); //needs to always be the same for each Object } return hash; } 

这里明显的权衡是对同一个哈希值进行多次计算的可能性,但是如果备选方案是一个可能具有更糟糕影响的synchronized哈希代码。

这在技术上是线程安全的,虽然冗余。

这取决于它是如何使用的。 其他数据。 类封装了一个行为,因此如果没有其他变量,变量通常几乎没有意义。 在这种情况下,保护(*)属于一起的数据成员(或整个对象)可能更好,而不仅仅是一个整数。 如果你这样做,那么AtomicInteger是一个不必要的性能AtomicInteger

(*)使用通用线程安全机制:互斥,信号量,监视器等。

线程安全不仅与primefacesint赋值有关,还需要仔细设计锁定模式以获得代码的一致性。

如果您有两个具有公共数据名称的Account类,请考虑以下简单代码。

 Account a; ... int withdrawal = 100; if(a.Balance >= withdrawal) { // No atomic operations in the world can save you from another thread // withdrawing some balance here a.Balance -= withdrawal } else { // Handle error } 

坦率地说。 在现实生活中,拥有primefaces作业很少能够解决我的现实生活并发问题。