gpt4 book ai didi

c++ - 当只有 1 个线程经常使用某个对象而其他线程很少使用该对象时,如何最大限度地减少该对象的互斥锁定?

转载 作者:行者123 更新时间:2023-12-02 14:14:10 24 4
gpt4 key购买 nike

场景

假设有“Thread_Main”和“Thread_DB”,具有共享的SQLite数据库对象。可以保证的是,

  • “Thread_main”很少使用 SQLite 对象进行读取(即 SELECT())
  • “Thread_DB”大部分时间使用 SQLite 对象进行各种 INSERTUPDATEDELETE 操作

为了避免数据竞争和 UB,SQLite 应使用 SQLITE_THREADSAFE=1(默认)选项进行编译。这意味着,在每次操作之前,都会锁定一个内部互斥量,这样 DB 在读取时不会写入,反之亦然。

"Thread_Main"    "Thread_DB"    no. of operation on DB
============= =========== ======================
something INSERT 1
something UPDATE 2
something DELETE 3
something INSERT 4
... ... ... (collapsed)
something INSERT 500
something DELETE 501
... ... ... (collapsed)
something UPDATE 1000
something UPDATE 1001
... ... ... (collapsed)
SELECT INSERT 1200 <--- here is a serious requirement of mutex
... ... ... (collapsed)

问题

如上所示,在数百次操作中,仅偶尔需要一次真正的互斥量。然而,为了保护这个小情况,我们必须锁定它的所有操作。

问题:有没有一种方法可以让“Thread_DB”大部分时间持有互斥量,从而不需要每次都加锁?仅当“Thread_Main”请求时才会发生锁定/解锁。

注释

  • 一种方法是在“Thread_DB”中对 SELECT 进行排队。但在运行多个数据库的较大场景中,这会减慢响应速度并且不是实时的。不能让主线程一直等待。
  • 我还考虑过有一个“Thread_Main”整数/ bool 变量,它表明“Thread_Main”想要SELECT。现在,如果当时“Thread_DB”中正在运行任何操作,则可以解锁互斥锁。这可以。但是,如果该 SQLite 对象上没有运行可写操作,则“Thread_main”将继续等待,因为“Thread_DB”中没有可解锁的操作。这将再次延迟甚至挂起“Thread_Main”。

最佳答案

这里有一个建议:稍微修改一下您的程序,使 Thread_Main 无法访问共享对象;只有Thread_DB 能够访问它。完成此操作后,您根本不需要进行任何序列化,并且 Thread_DB 可以充分高效地工作。

当然美中不足的是Thread_Main有时确实需要与DB对象交互;如果它没有任何访问权限,它怎么能做到这一点?

该问题的解决方案是消息传递。当 Thread_Main 需要对数据库执行某些操作时,它应该将某种类型的 Message 对象传递给 Thread_DB。消息对象应包含表征所需交互所需的所有详细信息。当 Thread_DB 接收到 Message 对象时,Thread_DB 可以调用它的execute(SQLite & db) 方法(或者任何你想调用的方法),此时可以在 Thread_DB 线程的上下文中进行必要的数据插入/提取。当交互完成后,任何结果都可以存储在 Message 对象中,然后可以将 Message 对象传递回主线程,以便主线程处理结果。 (主线程可以阻塞等待Message发回,也可以继续与DB线程异步操作,由你决定)

关于c++ - 当只有 1 个线程经常使用某个对象而其他线程很少使用该对象时,如何最大限度地减少该对象的互斥锁定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59526616/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com