一、LWLock简介
大家好!今天我们来聊一聊 openGauss 的LWLock(轻量级锁),他是一种用于并发控制的机制,旨在提高数据库的性能和响应能力,尤其是在多线程和多进程环境下。接下来,我会带大家一步步解析相关代码,并提供优化实践的建议。 希望通过这篇文章,你能对 openGauss 的LWLock有更深刻的理解,并应用到自己的项目中!
二、LWLock相关结构
LWLock的相关数据结构如下:
typedef enum LWLockMode {
LW_EXCLUSIVE, // 排他锁
LW_SHARED, // 共享锁
LW_WAIT_UNTIL_FREE /* A special mode used in PGPROC->lwlockMode,
* when waiting for lock to become free. Not
* to be used as LWLockAcquire argument */
} LWLockMode;
typedef struct LWLock {
uint16 tranche; /* tranche ID */
pg_atomic_uint32 state; /* state of exlusive/nonexclusive lockers */
dlist_head waiters; /* list of waiting PGPROCs */
#ifdef LOCK_DEBUG
pg_atomic_uint32 nwaiters; /* number of waiters */
struct PGPROC* owner;
#endif
#ifdef ENABLE_THREAD_CHECK
pg_atomic_uint32 rwlock;
pg_atomic_uint32 listlock;
#endif
} LWLock;
LWLockMode定义了一个枚举类型 ,表示轻量锁的三种操作模式,排他锁、共享锁和一种特殊模式。其中排他锁表示当前锁只能被单个线程持有,共享锁表示多个线程可以同时持有该锁,但不能同时存在排他锁,还有一种特殊模式,仅用于内部操作,不作为 LWLockAcquire 函数的参数,表示当前线程正在等待锁被完全释放。
LWLock表示一个锁对象,其定义如下:
1、tranche,相当于锁的ID,表示锁所属的分类,在调试或性能监控中,用于标识某个锁的用途。
2、state,保存锁的状态,包括当前是否被持有,以及持有者的类型。
3、waiters,双向链表,存储等待获取该锁的进程(或线程),链表的节点表示等待锁的数据库进程。
4、nwaiters,表示等待该锁的进程数量。
5、owner,用于记录最后一个持有排他锁的进程。
6、rwlock,用于读写锁的状态管理。
7、listlock:用于保护 waiters 链表的并发访问。
三、LWLock 初始化
在代码里面,初始化分为三个步骤:
1、函数开始时会检查是否已经分配内存上下文,若已存在则删除旧上下文。
2、使用 memset_s 清零 ctl 结构以避免内存污染,调用 securec_check 检查 memset_s 的返回值,确保操作的安全性。
3、使用 HASHCTL结构配置哈希表的参数,如键大小,条目大小以及内存上下文,调用hash_cre ate创建哈希表。
static void init_lwlock_stats(void)
{
……
HASHCTL ctl;
static MemoryContext lwlock_stats_cxt = NULL;
static bool exit_registered = false;
if (lwlock_stats_cxt != NULL) {
MemoryContextDelete(lwlock_stats_cxt);
}
lwlock_stats_cxt = AllocSetContextCreate(t_thrd.top_mem_cxt, "LWLock stats", ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE);
MemoryContextAllowInCriticalSection(lwlock_stats_cxt, true);
errno_t rc = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl));
securec_check(rc, "\0", "\0");
ctl.keysize = sizeof(lwlock_stats_key);
ctl.entrysize = sizeof(lwlock_stats);
ctl.hcxt = lwlock_stats_cxt;
lwlock_stats_htab = hash_create("lwlock stats", 16384, &ctl, HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
……
}
四、LWLock 加锁
在代码里LWLockAcquire函数负责整个加锁过程,需要传入获取的LWLock对象的指针,锁的模式(共享或者排他),还需要传入是否需要更新锁的标识,该函数采用无限循环的方式(for (;
标签:cxt,lock,storage,剖析,LW,LWLock,lwlock,openGauss From: https://www.cnblogs.com/zhou157/p/18607885