每條彙編指令原子 第4章 原子操作

2021-10-12 19:43:07 字數 1816 閱讀 6566

有一件事情,你不得不承認,c語言相對彙編來說是高階語言,為什麼,因為高階語言會形成封裝,比如,我需要把乙個變數a++,對於cpu來說,先從記憶體裡把這個變數讀進運算暫存器,然後運算增加,然後再把a寫入原來的記憶體位置。

什麼是原子操作?

不被其他事件打斷的操作,就叫做原子操作。

老外是用這樣一句話來說明這個

「do this, and don』t get interrupted while doing this.」

我們在cpu裡面,想把a++,執行一次,因為是c語言實現的,所以這個指令會被編譯成組合語言,變成了好幾個指令,比如cpu從記憶體中拿a到暫存器裡面,這個操作,就可能被其他事件打斷,有可能是中斷,也可能是定時器,也有可能是cpu執行緒排程等其他原因。

為什麼我們要討論原子操作?

如果沒有多執行緒程式設計的同學,應該對這個沒概念,也不會知道這個會引起什麼問題,這樣好了,我來寫乙個例子。

#include #include #include #include #include  #define gettidv1() syscall(__nr_gettid)  #define gettidv2() syscall(sys_gettid)long int num = 0;void * th(void * ptr)    //sleep(1);    //printf("im %s id:%ld number:%ld\n",(char*)ptr,gettidv1(),num);}int main(int argc,char ** ar**)    pthread_t thread2 = -1;    if(pthread_create(&thread2,null,th,"th2")!=0)                  while(1)    ;}
makefile檔案

all:  gcc thread.c -o thread -pthreadclean:  rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions
輸出結果

linux@ubuntu:~/linuxbook/linux-c/pthread$ make && ./threadgcc thread.c -o thread -pthreadim main id:7503 number:0im main id:7503 number:638925977im main id:7503 number:1334751130im main id:7503 number:1997474779
總結下原因

我相信很多人應該看過類似的例子,但是可能沒有自己去寫過,而且可能寫的時候,給的變數比較小,就有可能導致看到的結果不一樣。

我說下原因,因為num++ ,這個操作不是原子的,就是說他在幹活的時候,有可能被其他東西打斷。

執行緒1在執行第一步的時候,cpu的控制器被排程給執行緒2使用了,然後呢,執行緒2 就做自己的事情,把num運算成1了,然後cpu控制權又回來到執行緒1這裡,因為執行緒1剛才上一次的運算還沒有完成,他就繼續用原來暫存器裡面的資料進行運算,然後num最後還是1。

可以看到乙個問題的是,執行緒2的這次操作被忽略了,實際上他打工幹活了,但是包工頭沒有給他記賬,結果後面結賬的時候,也沒有給他工錢,這個就比較悲劇了。

之前文章有點長,以後還是簡化文章,覺得不錯,支援一下。

第4章 操作列表

4.1.1 迴圈 遍歷 1.for迴圈 python中for迴圈的執行部分需要縮排,但是想要在迴圈之後再做其他執行,那麼該執行部分不需要縮排 輸出為 注 如果第二個print 不縮排,那麼 i can t wait to see your next trick,只會輸出一次,並且名字是carolin...

python第4章操作列表練習

4 3 數到 20 使用乙個 for 迴圈列印數字 1 20 含 for value in range 1,21 忘加冒號 print value 4 4 一百萬 建立乙個列表,其中包含數字 1 1 000 000,再使用乙個 for 迴圈將這 些數字列印出來 如果輸出的時間太長,按 ctrl c停...

筆記 組合語言 第10章 CALL和RET指令

10.0 概述 call和ret指令都是轉移指令,它們都修改ip,或同時修改cs和ip。它們經常被用來共同實現子程式的設計。10.1 ret和retf ret指令用棧中的資料,修改ip的內容,即相當於 pop ip retf指令用棧中的資料,修改cs和ip的內容,即相當於 pop ip pop cs...