搭建VPS网站时,除了源码,还需哪些关键因素?
摘要:vps 网站异常,有一套源码做网站还差什么,wordpress 破解,ps怎么做网站logo文章目录 前言详解解决多线程下的问题 Happens-before原则总结as-if-serial语义happens-before的例子 前言 &a
vps 网站异常,有一套源码做网站还差什么,wordpress 破解,ps怎么做网站logo文章目录 前言详解解决多线程下的问题 Happens-before原则总结as-if-serial语义happens-before的例子 前言
as-if-serial原则是Java内存模型中的一个重要概念。该规则规定#xff1a;不管怎么重排序#xff08;编译期间的重排序#xff0c;指令级并行的重排序as-if-serial原则是Java内存模型中的一个重要概念。该规则规定不管怎么重排序编译期间的重排序指令级并行的重排序内存系统的重排序等单线程程序的执行结果不能被改变。编译器、runtime和处理器都必须遵守as-if-serial语义。
为了获取更好的性能编译器和处理器常常会对指令做重排序但是他们必须遵守数据依赖性即在不改变单线程程序执行结果的前提下进行指令重排序。例如对于以下代码
int a 1; //语句1
int b 2; //语句2
int c a b; //语句3语句1和语句2没有数据依赖性可以重排序。但是语句3依赖于语句1和语句2所以它不能被重新排序到语句1或语句2之前。
然而这个原则只适用于单线程对于多线程就需要遵守happens-before原则确保线程间操作的有序性和可见性。
详解
as-if-serial原则是说不考虑并发编程的情况Java程序的执行结果应该与该程序在串行化环境中的执行结果一致。简单来说就是程序在执行过程中无论如何重新排序例如编译器的优化处理器的优化只要最终呈现出的执行结果与串行执行的结果一致那么这样的重排序是被允许的。
例如考虑以下代码
int a 1;
int b 2;
int c a b;依照as-if-serial原则虽然在执行过程中可能会将int b 2;语句移到int c a b;之后执行但是最终的执行结果c的值仍然与串行化执行的结果一致。
但在并发环境下as-if-serial原则可能会导致问题。例如
public class Counter {private int count 0;public void increment() {count;}public int getCount() {return count;}
}
在并发环境下如果有两个线程同时执行 increment() 方法由于 as-if-serial 原则编译器或处理器可能将 count 重排序为两个操作先读取 count 的值然后再写回 count1 的值。在两个线程并发执行的情况下可能第一个线程读取了 count 的值然后第二个线程也读取了 count 的值然后两个线程都将 count1 的值写回导致 count 的值只增加了 1而不是预期的 2。下面是一个更具体的例子来说明 as-if-serial 原则可能导致的问题java
public class Example {private int a 0;private int flag 0;public void writer() {a 1; //1flag 1; //2}public void reader() {if (flag 1) //3{int i a; //4}}
}在这个例子中假设有两个线程一个线程执行 writer() 方法另一个线程执行 reader() 方法。按照 as-if-serial 原则编译器或处理器可能会将 writer() 方法中的两行代码的顺序交换即先执行 flag 1然后再执行 a 1。如果这样的重排序发生reader() 方法可能会在 a 被赋值之前就读取到 flag 的值为 1然后读取到 a 的值为 0而不是预期的 1。
解决多线程下的问题
Java通过使用volatile关键字来解决这个问题。
当一个变量被volatile修饰后它将具备两种特性 可见性Visibility: 当一个线程修改了一个volatile变量的值新值对于其他线程来说是可以立即得知的。 禁止指令重排序优化普通的变量仅仅会满足1而被volatile修饰过的变量由于禁止指令重排序优化可以满足2。
这两种特性使得volatile变量在并发编程中非常有用。
例如在上面的例子中如果flag变量被声明为volatile那么两个线程看到的flag永远都是最新的如果writer线程更改了flag的值reader线程立刻就能看到这就解决了可见性问题。同时对一个volatile变量的任何写操作都会立即刷新到主存因此在写操作后的任何读操作都会看到这个新值。
volatile关键字还有一个额外的特性就是禁止指令重排序。
