編譯重排序
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里排重排序怎麼做工作急用.
高級篩選,不選擇重復記錄,結果復制到新表。