上回說到實現了乙個無鎖的 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...