delphi 利用 InterlockedCompareExchange 實現主執行緒維一鎖等待
在進行資源鎖定時,一般是執行緒之間進行互動,很少需要在主執行緒也對資源進行鎖定。
不過在一些複雜的業務中,存在子執行緒與主執行緒的互動,且一些資源也同步在主執行緒中使用時,主執行緒資源鎖,就有存在的必要。
假定有一個需求,在SQLITE更新時,需要共同一個更新元件,以減少資源建立與釋放及相對應記憶體回收的需求,則此時的每一個更新,就有先鎖定再更新的必要。
廢話不多說,直接上程式碼。
var WaitSQlite:Integer;//SQLITE 寫入互斥鎖 FunctionGetWaitSQlite:Boolean;//取得鎖資源 begin Result:=False; //LOG.WriteLog('進入等待'); whileInterlockedCompareExchange(WaitSQlite,1,0)=WaitSQlite do begin Sleep(1); end; Result:=True; // LOG.WriteLog('0000000000000000000000000離開等待'); end; FunctionFreeWaitSQlite:Boolean; //釋放鎖資源 begin InterlockedCompareExchange(WaitSQlite,0,1) ; //LOG.WriteLog('1111111111111111111111111釋放等待'); end;
function EXECLocalSQLite(Sql: string): Boolean; begin Result := False; GetWaitSQlite; try try FDQuerySQLiteExec.Connection:=FDConSQLite; FDQuerySQLiteExec.close; FDQuerySQLiteExec.Sql.clear; FDQuerySQLiteExec.Sql.text := Sql; FDQuerySQLiteExec.EXECSQL; except on E: Exception do begin LOG.WriteLog(Sql); LOG.WriteLog('EXECLocalSQLite 執行SQL報錯:' + E.Message); end; end; finally FreeWaitSQlite end; end;
GetWaitSQlite在 WaitSQlite 值為1時,會一直迴圈等待,直接該值為0,然後呼叫InterlockedCompareExchange (該函式是一個粒度很小的鎖控制,因此不擔心並行修改問題)把值修改為1, 後返回,執行對應的SQL,執行完後,把該值修改為0,供下一次呼叫。 如果是EXE中執行,記得加上Application.ProcessMessages;不然介面會被卡死。