首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >原子指令: IFs和Loops

原子指令: IFs和Loops
EN

Stack Overflow用户
提问于 2015-10-31 19:20:35
回答 2查看 1.1K关注 0票数 0

在并发编程中,IF语句和循环(如while或do while原子指令)是吗?

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

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-11-03 10:24:56

在Java中,没有额外工作的唯一原子性的东西是赋值。其他任何东西都需要同步,要么通过声明方法synchronized,要么使用synchronized块。您还可以使用来自java.concurrent的类--其中一些类使用一些更聪明的机制来确保同步,而不仅仅是声明synchronized方法(可能比较慢)。

关于if-语句和您在评论中提出的关于比较n == m的问题

比较不是原子的。首先必须加载n的值(在这里,m的值仍然可以更改),然后必须加载m的值,然后计算实际的比较(此时nm的实际值可能已经与比较中的实际值不同)。

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

代码语言:javascript
复制
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,它们仍然可以并行执行。
代码语言:javascript
复制
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吗?

票数 0
EN

Stack Overflow用户

发布于 2015-10-31 19:24:42

它们可以具有任意大的和复杂的(即非原子的)布尔表达式,需要进行计算。防止比赛条件涉及到他们(如果这就是你所说的“安抚”的意思)的一种方法是使用某种锁定机制。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33455614

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档