在进行资源锁定时,一般是线程之间进行交互,很少需要在主线程也对资源进行锁定。
不过在一些复杂的业务中,存在子线程与主线程的交互,且一些资源也同步在主线程中使用时,主线程资源锁,就有存在的必要。
假定有一个需求,在SQLITE更新时,需要共同一个更新组件,以减少资源建立与释放及相对应内存回收的需求,则此时的每一个更新,就有先锁定再更新的必要。
废话不多说,直接上代码。
var WaitSQlite:Integer;//SQLITE 写入互斥锁 Function GetWaitSQlite:Boolean;//取得锁资源 begin Result:=False; //LOG.WriteLog('进入等待'); while InterlockedCompareExchange(WaitSQlite,1,0)=WaitSQlite do begin Sleep(1); end; Result:=True; // LOG.WriteLog('0000000000000000000000000离开等待'); end; Function FreeWaitSQlite: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;不然界面会被卡死。