再論 無鎖資料結構(下)

2021-05-04 09:27:44 字數 2586 閱讀 4085

上回說到實現了乙個無鎖的 wrrm 的指標保護演算法,但存在乙個問題是:寫執行緒在更新指標之後,更新游離物件引用計數之前,被強制殺死,會造成讀取執行緒的活鎖,這有悖乙個原則……好像叫什麼「寫無關原則」,即使乙個執行緒崩潰也不該對其他執行緒造成太大影響(當然,所有執行緒全部被殺的話,啥演算法都玩完), 下面的方法,可解決那個個可能存在的活鎖問題:

在object裡面再增加乙個成員,int ntmprelease ,用來在游離物件的引用計數變為有效值前記錄臨時的釋放次數,在寫執行緒更新游離物件引用計數時,更新為當前的引用計數,減去這個值。其他實現不變。

具體**如下:

#include "stdafx.h"

#include

#include

#include

#include

//物件的引用

struct object

;__int64 nall;

};int ntmprelease;    //物件臨時使用的,釋放計數,為解決 寫執行緒意外死亡造成的 活鎖問題

};typedef struct object object;

//物件的擁有者

struct owner

;__int64 nall;

};};

typedef struct owner owner;

#ifdef _debug

long g_nnewcount = 0;

long g_ndelcount = 0;

#define debug_inc( x )    interlockedincrement( (volatile long*)&x)

#else

#define debug_inc( x )   

#endif

#define invalid_ref_count    (-100)    //標識乙個無效的引用計數

//全域性的引用者

owner    g_owner;

//獲得物件指標

object* acquire()

while ( stuold.nall != interlockedcompareexchange64( (longlong volatile*)&g_owner.nall , stunew.nall , stuold.nall ) );

return stunew.pobject;

}void release( object* pobject )

else if( stutest.pobject != stuold.pobject )//原物件已被更新

} while ( true );

}if( !breleaseinowner )

else if( stutestobj.nref_count != stuoldobj.nref_count )//物件的引用計數已經更新

} while ( true );

}if( breleaseobject )

else if( nret < 0 )}}

}bool update( object* pold , object* pnew )

break;

}} while (true);

break;

}else if( stutest.pobject != stuold.pobject )

} while ( true );

return bret;

}uint callback readthread( void* pcount )

while ( ucount > 0 );

return 0;

}uint callback writethread( void* pcount )

if( pobject != null )

pobject = acquire();

debug_inc( g_nnewcount );

pnew = new object;

} while ( !update( pobject , pnew ) );

if( pobject != null )

ucount --;

} while ( ucount > 0 );

return 0;

}int main(int argc, char* argv)

至此,乙個wrrm 的指標保護物件終於完成了,不會發生活鎖,如果有執行緒被異常終止,也和hazard 指標一樣會造成一點洩漏。

不過這個實現 目的旨在保護指標指向的資源,任何c/c++物件都可使用(c語言把new/delete換成malloc/free),系統開銷也

比hazard 指標方案開銷要小,方案的結構上好像有點共軛關係,就叫 無鎖共軛資料結構吧 。

參考文獻

劉未鵬 同學翻譯的:(真是個大善人啊)

無鎖資料結構三 無鎖資料結構的兩大問題

struct tagged ptr tagged ptr t p ptr p tag 0 tagged ptr t p,unsigned int n ptr p tag n t operator const 標籤作為乙個版本號,隨著標籤指標上的每次cas運算增加,並且只增不減。一旦需要從容器中非物理...

再訪資料結構

資料結構是我當年難以逾越的一道溝 多年以後,先從最簡單的線段樹下手吧 寫了乙個 洛谷線段樹的模板題 區間加 和 區間求和 很簡單,算是留念吧 created by dell on 2020 3 1.include include include include define maxn 100005 ...

資料結構無頭單鏈表

template class slist node t data node head node tail int size public slist 複製建構函式 slist const slist sl slist 尾插 void slistpushback t data 尾刪 void slis...