Java中与.Net的Interlocked类相对应的是什么?

16

如何在Java中以原子性和线程安全的方式修改一个int?

原子性地增加、测试和设置等操作?

3个回答

31

2
如果你只需要它提供的有限操作集,那就没问题了。问题中的“等等”表明需要更多的灵活性。 - skaffman
7
没问题。如果他想要更多的话,他应该更明确地表达。目前来看,AtomicInteger似乎是正确的答案。 - Brian Agnew
2
还可以看一下java.util.concurrent包中的其他类。它们对于“等等”这样的东西可能会有帮助。 - Roland Schneider

1

通过同步函数可以实现线程安全。 将您的 int(或类似数据)封装在一个类中,该类通过同步方法提供所需的功能,例如:

public class X
{
  protected int x;
  public synchronized void set( int value )
  {
    x = value;
  }
}

您还可以使用java.util.concurrent.atomic包中的类,例如AtomicInteger或AtomicIntegerArray。

为什么这个答案不起作用

我只是想确保指出这个答案的问题所在,以防有人认为synchronized可以用来解决线程竞争效应。

| Thread A      | Thread B         | 
|---------------|------------------|
| read x (x=4)  |                  |
|               | read x (x=4)     |
| Calculate 4+1 |                  |
| EAX ← 5       |                  |
|               | Calculate 4+1    |
|               | EAX ← 5          |
| Start sync    |                  |
| {             | Start sync       |
| { x ← 5       |    wait          |
| {             |    wait          |
| End sync      |    wait          |
|               | {                | 
|               | { x ← 5          |
|               | {                | 
|               | End sync         |

操作的最终结果:
x = 4;
x += 1;
x += 1;

这意味着x = 5而不是6。

volatile关键字也存在同样的问题。 volatile关键字不能保护你免受线程影响。 volatile关键字只确保:

  • 在读取变量之前刷新缓存
  • 在写入值后刷新缓存

严格来说,volatile确保内存操作不会在volatile变量周围重新排序。 这意味着您仍然会遇到以下问题:

  • 从x读取
  • 写入x

的问题。


3
同步锁相当沉重,不太适合作为Interlocked的有效替代品。人们使用Interlocked是因为它快速且轻量级。 - Deeko

0
private final static AtomicInteger at = new AtomicInteger();

public void run() {
    at.set(7);
    int i = at.incrementAndGet();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接