Loops 原子指令:IFs和循环
在并发编程中,IF语句和循环是否是while或do-while原子指令 如果没有,是否有一种原子化实现它们的方法Loops 原子指令:IFs和循环,loops,if-statement,concurrency,atomic,Loops,If Statement,Concurrency,Atomic,在并发编程中,IF语句和循环是否是while或do-while原子指令 如果没有,是否有一种原子化实现它们的方法 编辑:修复了我的一些狡猾的英语。这些可以有任意大而复杂(即非原子)的布尔表达式需要计算。防止涉及它们的竞争条件的一种方法(如果这就是你所说的“安抚”)是使用某种锁定机制。在Java中,只有分配是原子的,没有任何额外的工作。任何其他内容都需要同步,可以通过声明方法synchronized或使用synchronized块。您还可以使用java.concurrent中的类-其中一些类使用一
编辑:修复了我的一些狡猾的英语。这些可以有任意大而复杂(即非原子)的布尔表达式需要计算。防止涉及它们的竞争条件的一种方法(如果这就是你所说的“安抚”)是使用某种锁定机制。在Java中,只有分配是原子的,没有任何额外的工作。任何其他内容都需要同步,可以通过声明方法
synchronized
或使用synchronized
块。您还可以使用java.concurrent
中的类-其中一些类使用一些更聪明的机制来确保同步,而不仅仅是声明方法synchronized
什么往往比较慢
关于if语句和您在关于比较的评论中提出的问题
n==m
:
比较不是原子的。首先必须加载n
的值(此处m
的值仍然可以更改),然后必须加载m
的值,然后评估实际比较(此时n
和m
的实际值可能已经不同于比较中的值)
如果希望同步,则必须执行以下操作:
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
上获取锁,而新整数(1)
在t2
上获取锁。因此,即使两个线程都锁定在新整数(2)
上,它们仍然可以并行执行任务n
您是否考虑过使用mutable
AtomicInteger
?对并发线程进行“安抚”意味着什么。我的意思是,有没有一种方法可以将实际语句(IFs或循环)算作原子指令。在任何现代平台上,最强大的原子操作是比较和交换(CAS)。你可以自己用谷歌搜索它的算法。为了获得更复杂的选择序列的原子性,您需要使用额外的同步机制,例如锁。如果要计算的表达式只是比较两个整数,那么如何?如果(n==m)而(n==v){
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);
}
}
}