编译重排序
A. 什么是指令重排
什么是指令重排序?
有两个层面:
**在虚拟机层面,**为了尽可能减少内存操作速度远慢于CPU运行速度所带来的CPU空置的影响,虚拟机会按照自己的一些规则(这规则后面再叙述)将程序编写顺序打乱——即写在后面的代码在时间顺序上可能会先执行,而写在前面的代码会后执行——以尽可能充分地利用CPU。拿上面的例子来说:假如不是a=1的操作,而是a=new byte1024*1024,那么它会运行地很慢,此时CPU是等待其执行结束呢,还是先执行下面那句flag=true呢?显然,先执行flag=true可以提前使用CPU,加快整体效率,当然这样的前提是不会产生错误(什么样的错误后面再说)。虽然这里有两种情况:后面的代码先于前面的代码开始执行;前面的代码先开始执行,但当效率较慢的时候,后面的代码开始执行并先于前面的代码执行结束。不管谁先开始,总之后面的代码在一些情况下存在先结束的可能。
**在硬件层面,**CPU会将接收到的一批指令按照其规则重排序,同样是基于CPU速度比缓存速度快的原因,和上一点的目的类似,只是硬件处理的话,每次只能在接收到的有限指令范围内重排序,而虚拟机可以在更大层面、更多指令范围内重排序。硬件的重排序机制参见《从JVM并发看CPU内存指令重排序(Memory Reordering)》
java提供了两个关键字volatile和synchronized来保证多线程之间操作的有序性,volatile关键字本身通过加入内存屏障来禁止指令的重排序,而synchronized关键字通过一个变量在同一时间只允许有一个线程对其进行加锁的规则来实现。
在单线程程序中,不会发生“指令重排”和“工作内存和主内存同步延迟”现象,只在多线程程序中出现。
1)编译器优化的重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。
2)指令级并行的重排序。现代处理器采用了指令级并行技术(Instruction-LevelParallelism,ILP)来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
3)内存系统的重排序。由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行
B. excel 用vba 多重排序如何编写呢
排序可以用sort,至于统计就复杂了,简单的就调用函数或者直接计算,复杂点的就是用数组,不是三言两语可以回答的。
C. 指令重排序会破坏happens-before原则吗
感觉你对JMM理解有些偏差,刚好最近我也在看这块的知识。
下面谈谈我的理解:
重排序一般分为指令重排序和编译器重排序,重排序的最终结果当然是提高吞吐量,单位时间能执行更多的指令
然而有些指令重排序是必须要禁止的,比如单例模式的双重检查,多线程的场景下会出事的。
happen-before规则保证了内存的可见性,要保证内存可见性,就得禁止一些指令的重排序。所以说一个happens-before规则对应多个禁止指令重排序的规则,目的是方便程序员的理解。简单讲就是说要保证内存可见性,就得禁止一些指令重排序,具体禁止哪些重排序哪就不是我们考虑的了,我们只要理解happens-before规则就好了。
举个例子:
一个线程内包装语义的串行性。这使得不论你怎么重排序也好,你排序完之后的结果必须和没有排序的语义是一样的,这也一定程度规定了一些必须遵守的纪律,要不程序乱套了,执行完了也没有用啊。
D. Java如果重排序,为什么打断点看的是顺序的
添加断点测试可以直接在要测试的代码处,双击鼠标左键,出现一个蓝色小点,说明添加断点成功;
接下来是测试,在代码页面点击鼠标右键,选择debug ->debug as myeclipse/eclipse application。
以debug方式运行java程序后,可以执行以下操作:
(F5)单步执行程序,遇到方法时进入;
(F6)单步执行程序,遇到方法时跳过;
(F7)单步执行程序,从当前方法跳出;
(F8)直接执行程序。遇到断点时暂停。
另外,在debug时,会有很多有用信息显示在debug框里,如堆栈信息,需要自己实践;在程序界面里,鼠标移到变量上时会有当前变量的属性值。
E. java指令重排序,happens-before的问题
重排序有一条原则,就是单线程运行这段代码不能影响得到的结果(这段代码虽然另起一个线程,但本身是由一个线程“引发”的)所以顺序没变,这也是很多人试的结果——没变。但提到重排序理论上又觉得可能变,所以以上解释算是我个人理解吧。重排序旨在尽可能的利用流水思想,复用寄存器减少读写,但最根本的还是要保障正确性,否则效率高没一点意义。编译器的行为应该还是慎重的(这里的例子应该也是编译时重排序)
F. c语言 文件内容的重新排序
采用插入排序,通过排索引加速。C代码:
#include <stdio.h>
#define NATION_MAX 256
#define LINE_MAX 1000
#define HEADER_SIZE 256
typedef struct
{
int No;
char Nation[NATION_MAX];
int gold, silver, bronze, sum;
}Medal;
int loadMedal(Medal *medals, char *header, const char *fileName)
{
int n = 0;
FILE *fp = fopen(fileName, "r");
if(!fp) return 0;
fgets(header, HEADER_SIZE, fp);
while(fscanf(fp, "%d%s%d%d%d%d", &(medals[n].No), medals[n].Nation,
&(medals[n].gold), &(medals[n].silver), &(medals[n].bronze),
&(medals[n].sum)) == 6){
n ++;
if(n >= LINE_MAX) return n;
}
fclose(fp);
return n;
}
void showMedal(Medal *medals, char *header, int nMedal, int *sorted)
{
int i, index;
fputs(header, stdout);
for(i = 0; i < nMedal; i ++) {
index = sorted[i];
printf("%d\t%s\t%d\t%d\t%d\t%d\n", medals[index].No,
medals[index].Nation, medals[index].gold,
medals[index].silver, medals[index].bronze, medals[index].sum);
}
}
void sortByNation(Medal *medals, int nMedal, int *sorted)
{
int i, j;
int key;
int *a = sorted;
int index;
for(j = 1; j < nMedal; j ++){
key = medals[a[j]].Nation[0];
index = a[j];
for(i = j - 1; (medals[a[i]].Nation[0] > key) && (i >= 0); i--){
a[i+1] = a[i];
}
a[i+1] = index;
}
}
void sortBySum(Medal *medals, int nMedal, int *sorted)
{
int i, j;
int key;
int *a = sorted;
int index;
for(j = 1; j < nMedal; j ++){
key = medals[a[j]].sum;
index = a[j];
for(i = j - 1; (medals[a[i]].sum > key) && (i >= 0); i--){
a[i+1] = a[i];
}
a[i+1] = index;
}
}
void resetIndex(int *sorted, int nMedal)
{
int i;
if(nMedal > LINE_MAX) return ;
for(i = 0; i < nMedal; i++){
sorted[i] = i;
}
}
int main()
{
Medal medals[LINE_MAX];
int sorted[LINE_MAX];
char header[HEADER_SIZE];
int nMedal;
nMedal = loadMedal(medals, header, "medal.txt");
resetIndex(sorted, nMedal);
/* showMedal(medals, header, nMedal, sorted); */
/* 按国家首字母排序*/
sortByNation(medals, nMedal, sorted);
/* 显示 */
showMedal(medals, header, nMedal, sorted);
/* 按总奖牌数排序 */
sortBySum(medals, nMedal, sorted);
/* 显示 */
showMedal(medals, header, nMedal, sorted);
return 0;
}
G. c语言 文件内容的重新排序问题
#include <stdio.h>
#include <stdlib.h>
//假设要打开的文件内容全是整数(如果是浮点数参照修改)
//数据与数据之间用空格分开
//每行多少数据可以不相同
//数组从小到大排序
void sortit(int *a,int n) {
int i,j,m;
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(a[i]>a[j]){
m=a[i];a[i]=a[j];a[j]=m;
}
}
//输出数组元素
void printit(int *a,int n){
int i;
for(i=0;i<n;i++){
printf("%5d",a[i]);
if (i%10==9) printf("\n"); //设置每10个换行
}
}
//从文件fp中读取n个数据到a
void getdata(FILE *fp,int *a,int n){
int i;
fseek(fp,0,0);
for(i=0;i<n;i++)
fscanf(fp,"%d",&a[i]);
}
//获取文件中整数数椐的个数
int getdatabound(FILE *fp){
int i=0,n;
fseek(fp,0,0);
while(fscanf(fp,"%d",&n)!=EOF) i++;
return i;
}
int main(){
int n,*a;
char *myfile="d:\\data.txt";
FILE *fp;
if ((fp=fopen(myfile,"r"))==NULL){
printf("打开文件%s失败\n",myfile);
return 0;
}
n=getdatabound(fp); //获取该文件中有多少整数
printf("该文件共有%d个整数\n",n);
a=(int *)malloc(sizeof(int)*n); //分配n个整数的空间
getdata(fp,a,n); //从文件fp中读取n个数据到a
fclose(fp);
printf("排序前的数组\n");
printit(a,n); //输出数组的值
printf("\n");
sortit(a,n);
printf("排序后的数组\n");
printit(a,n);
printf("\n");
}
H. volatile怎么实现防止指令重排序的
当被问到要实现一个单例模式时,很多人的第一反应是写出如下的代码,包括教科书上也是这样教我们的。 1 2 3 4 5 6 7 8 9 10 11 public class Singleton { private static Singleton instance; private Singleton (){}
I. EXCEL里排重排序怎么做工作急用.
高级筛选,不选择重复记录,结果复制到新表。