原子指令:IF和循环

时间:2015-10-31 19:20:35

标签: loops if-statement concurrency atomic

是IF语句和循环,例如while和do while并发编程中的原子指令吗?

如果没有,有没有办法以原子方式实现它们?

编辑:修正了我的一些狡猾的英语。

2 个答案:

答案 0 :(得分:0)

这些可以任意大&需要计算的复杂(即非原子)布尔表达式。防止涉及他们的竞争条件的一种方法(如果你的意思是"安抚")是使用某种锁定机制。

答案 1 :(得分:0)

在Java中,唯一没有任何额外工作的原子是分配。其他任何事情都需要通过声明方法synchronized或使用synchronized块进行同步。您还可以使用java.concurrent中的类 - 其中一些使用一些更聪明的机制来确保同步,而不是仅仅声明方法synchronized往往会很慢。

关于if-statement以及您在评论中询问的有关比较n == m的问题:

比较不是原子的。必须加载n的第一个值(此处m的值仍然可以更改),然后必须加载m的值,然后评估实际比较(并且此时nm的实际值可能已经与比较中的实际值不同了。

如果你想让它同步,你就必须做这样的事情:

public class Test {

    private static final Object lock = new Object();

    public static void main(String[] args) {
        if (equals(1, 2)) {
            // do something (not synchronised)
        }
    }

    public static boolean equals(int n, int m) {
        synchronized (lock) {
            return n == m;
        }
    }

}

然而,这提出了一个问题为什么要这样做以及锁定应该是什么(以及与之共享的锁是什么线程)?我想看一些关于你的问题的更多背景,因为目前我看不出做这样的事情的任何理由。

您还应该记住:

  • 你无法锁定基元(你必须将这两个值都声明为Integer
  • 锁定null将导致NullPointerException
  • 获取值的值,而不是参考值。因为Java中的整数是不可变的,所以为字段分配新值将导致创建新锁,请参阅下面的代码。线程t1获取new Integer(1)上的锁定,而t2获取new Integer(2)上的锁定。因此,即使两个线程都锁定n,它们仍然可以并行处理。
public class Test {

    private static Integer n = 1;

    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread(() -> {
            synchronized (n) {
                System.out.println("thread 1 started");
                sleep(2000);
                System.out.println("thread 1 finished");
            }
        });
        Thread t2 = new Thread(() -> {
            synchronized (n) {
                System.out.println("thread 2 started");
                sleep(2000);
                System.out.println("thread 2 finished");
            }
        });

        t1.start();
        sleep(1000);
        n = 2;
        t2.start();

        t1.join();
        t2.join();
    }

    private static void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

}

您是否考虑过使用可变AtomicInteger