SQLite学习之路⑪ 互斥锁(2021SC@SDUSC)

SQLite 学习之路 第十一节 请求锁和销毁锁

请求互斥锁,sqlite3_mutex_enter()导致阻塞,sqlite3_mutex_try()返回SQLITE_BUSY。sqlite3_mutex_enter() 和 sqlite3_mutex_try()例程尝试键入一个互斥锁,如果另一个线程已经拥有这个互斥锁,sqlite3_mutex_enter()将阻塞,sqlite3_mutex_try()将返回SQLITE_BUSY,一旦成功键入, sqlite3_mutex_try() 接口将返回SQLITE_OK。被创建的互斥锁使用SQLITE_MUTEX_RECURSIVE可以被相同的线程多次键入。在这样的情况下,在另一个线程进入之前,互斥锁必须退出相同的次数。

sqlite3_mutex_try()例程很少被使用,仅仅是它被作为一种优化的时候被使用,因此该例程总是调用失败是正常的。TryEnterCriticalSection()接口只能在WinNT上可用,在 Win98系统的基础上,如果你尝试在没有预先做一些 #defines 定义的情况下使用该例程来阻止SQLite,一些windows编译器会控诉这种行为。出于这个原因,我们将省略这种优化。

请求互斥锁,sqlite3_mutex_enter()导致阻塞:

static void winMutexEnter(sqlite3_mutex *p){
#ifdef SQLITE_DEBUG
  DWORD tid = GetCurrentThreadId();
  assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
#endif
  EnterCriticalSection(&p->mutex);
#ifdef SQLITE_DEBUG
  assert( p->nRef>0 || p->owner==0 );
  p->owner = tid; //填写被引用的线程ID
  p->nRef++; //线程引用加1
  if( p->trace ){
    printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
  }
#endif
}
static int winMutexTry(sqlite3_mutex *p){
#ifndef NDEBUG
  DWORD tid = GetCurrentThreadId();
#endif
  int rc = SQLITE_BUSY;
  assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
  /*
  ** The sqlite3_mutex_try() routine is very rarely used, and when it
  ** is used it is merely an optimization.  So it is OK for it to always
  ** fail.
  **
  ** The TryEnterCriticalSection() interface is only available on WinNT.
  ** And some windows compilers complain if you try to use it without
  ** first doing some #defines that prevent SQLite from building on Win98.
  ** For that reason, we will omit this optimization for now.  See
  ** ticket #2685.
  */
  //TryEnterCriticalSection() 只在WinNT上才有
#if 0
  if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
    p->owner = tid;
    p->nRef++;
    rc = SQLITE_OK;
  }
#else
  UNUSED_PARAMETER(p);//void *
#endif
#ifdef SQLITE_DEBUG
  if( rc==SQLITE_OK && p->trace ){
    printf("try mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
  }
#endif
  return rc;
}

销毁锁
退出临界区时,引用数减1,当引用减为0时,删除被引用的ID记录。

sqlite3_mutex_leave() 例程退出一个互斥锁,这个互斥锁之前被同一个线程键入。如果这个互斥锁不是当前键入的或者不是当前分配的,这个行为是未定义的。SQLite永远也不会那样做。

static void winMutexLeave(sqlite3_mutex *p){
#ifndef NDEBUG
  DWORD tid = GetCurrentThreadId();
  assert( p->nRef>0 );
  assert( p->owner==tid );
  p->nRef--; //退出临界区时,引用数减1
  if( p->nRef==0 ) p->owner = 0;  //引用减为0时,删除被引用的ID记录
  assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
#endif
  LeaveCriticalSection(&p->mutex);
#ifdef SQLITE_DEBUG
  if( p->trace ){
    printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
  }
#endif
}
上一篇:SQLITE_BTREE_H


下一篇:玩转SQLite3:SQLite图形软件基本操作