Java并发之原子性、有序性、可见性及Happen Before原则
原子性
Java中的原子性是指一个操作或者多个操作,要么全部都执行并且执行的过程不会被任何因素中断,要么就全部都不执行。在Java中,原子性可以通过synchronized
和Lock
关键字实现。除此之外,Java实现了java.util.concurrent.atomic
包,提供了一系列原子性操作类,比如AtomicInteger
、AtomicLong
等等。这些原子性类中,常用的方法有:compareAndSet
、incrementAndGet
、decrementAndGet
等等。
有序性
Java中的有序性是指程序执行时,可能会对指令进行重排序,但是最终结果不变。在Java中,要保证有序性,可以使用volatile
关键字,或者是synchronized
和Lock
关键字。在使用volatile
时,会保证读写操作的原子性和有序性。此外,Java中还有一种特别的有序性,称为程序顺序原则(POO,Program Order Rule),POO指的是在一个线程中,程序顺序规则保证了代码按照写在代码中的顺序依次执行。
可见性
Java中的可见性是指当一个线程修改了某个共享变量的值时,其他线程是否能够立即知道这个变量被修改的事实。在Java中,要保证可见性,可以使用volatile
关键字,或者是synchronized
和Lock
关键字。使用volatile
关键字时,会强制线程每次都从主内存中读取变量的值,而不是从线程的本地缓存中读取。此外,Java中还有一种实现可见性的方法,就是使用synchronized
和Lock
关键字。
Happen Before原则
Java中的Happen Before原则是指,在一定的情况下,任何一个操作事件的执行结果都能被后续的操作事件所看到。Java中有一些规则,可以确保满足Happen Before原则,包括:
- 程序顺序原则(POO)
- 传递性
- volatile变量规则
- 锁规则
- 线程启动规则
- 线程中断规则
- 线程终结规则
其中,传递性规则表示:如果操作A Happen Before操作B,操作B Happen Before操作C,那么操作A Happen Before操作C。
示例说明
示例一
public class Example1 {
private int count = 0;
public synchronized void increase() {
count++;
}
public static void main(String[] args) throws InterruptedException {
final Example1 example = new Example1();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (int j = 0; j < 1000; j++) {
example.increase();
}
}).start();
}
Thread.sleep(5000);
System.out.println(example.count);
}
}
上述代码创建了一个Example1
类,该类中有一个成员变量count
,和一个同步方法increase
。通过创建10个线程,让它们同时访问increase
方法,每次访问后将count
自增1。由于synchronized
关键字的保证,该程序将可以保证原子性和可见性。最终执行结果应该是:10000
。
示例二
public class Example2 {
private volatile int value = 0;
public void setValue(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static void main(String[] args) throws InterruptedException {
final Example2 example = new Example2();
new Thread(() -> {
try {
Thread.sleep(1000);
example.setValue(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
while (example.getValue() == 0) {
Thread.sleep(100);
}
System.out.println("value: " + example.getValue());
}
}
上述代码创建了一个Example2
类,其中有一个成员变量value
,并且使用了volatile
关键字进行修饰。在主线程中,创建了一个线程,并且在该线程中1秒后将value
设置为1
。在主线程中,通过while
循环判断value
是否为0
。由于volatile
关键字的保证,可以保证在判断value
时,已经能获取到最新的value
值,因此该程序将可以保证可见性。最终执行结果应该是:value: 1
。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发之原子性 有序性 可见性及Happen Before原则 - Python技术站