1. 程式人生 > >多執行緒的那點兒事(之自旋鎖)

多執行緒的那點兒事(之自旋鎖)

【 宣告:版權所有,歡迎轉載,請勿用於商業用途。  聯絡信箱:feixiaoxing @163.com】

    自旋鎖是SMP中經常使用到的一個鎖。所謂的smp,就是對稱多處理器的意思。在工業用的pcb板上面,特別是伺服器上面,一個pcb板有多個cpu是很正常的事情。這些cpu相互之間是獨立執行的,每一個cpu均有自己的排程佇列。然而,這些cpu在記憶體空間上是共享的。舉個例子說,假設有一個數據value = 10,那麼這個資料可以被所有的cpu訪問。這就是共享記憶體的本質意義。

    我們可以看一段Linux 下的的自旋鎖程式碼(kernel 2.6.23,asm-i386/spinlock.h),就可有清晰的認識了,

  1. staticinlinevoid __raw_spin_lock(raw_spinlock_t *lock)  
  2. {  
  3.     asm volatile("\n1:\t"
  4.              LOCK_PREFIX " ; decb %0\n\t"
  5.              "jns 3f\n"
  6.              "2:\t"
  7.              "rep;nop\n\t"
  8.              "cmpb $0,%0\n\t"
  9.              "jle 2b\n\t"
  10.              "jmp 1b\n"
  11.              "3:\n\t"
  12.              : "+m" (lock->slock) : : "memory");  
  13. }  
上面這段程式碼是怎麼做到自旋鎖的呢?我們可以一句一句看看,


line  4: 對lock->slock自減,這個操作是互斥的,LOCK_PREFIX保證了此刻只能有一個CPU訪問記憶體
line  5: 判斷lock->slock是否為非負數,如果是跳轉到3,即獲得自旋鎖
line  6: 位置符
line  7: lock->slock此時為負數,說明已經被其他cpu搶佔了,cpu休息一會,相當於pause指令
line  8: 繼續將lock->slock和0比較,

line  9: 判斷lock->slock是否小於等於0,如果判斷為真,跳轉到2,繼續休息
line 10: 此時lock->slock已經大於0,可以繼續嘗試搶佔了,跳轉到1
line 11: 位置符 

    上面的操作,除了第4句是cpu互斥操作,其他都不是。所以,我們發現,在cpu之間尋求互斥訪問的時候,在某一時刻只有一個記憶體訪問許可權。所以,如果其他的cpu之間沒有獲得訪問許可權,就會不斷地檢視當前是否可以再次申請自旋鎖了。這個過程中間不會停歇,除非獲得訪問的許可權為止。


總結:
   1)在smp上自旋鎖是多cpu互斥訪問的基礎
   2)因為自旋鎖是自旋等待的,所以處於臨界區的程式碼應儘可能短
   3)上面的LOCK_PREFIX,在x86下面其實就是“lock”,gcc下可以編過,朋友們可以自己試試