iam*_*ind 6 c++ algorithm qt mutex micro-optimization
假设有“Thread_Main”和“Thread_DB”,有一个共享的 SQLite 数据库对象。可以保证的是,
SELECT())INSERT, UPDATE,DELETE操作为避免数据竞争和 UB,应使用SQLITE_THREADSAFE=1(默认)选项编译 SQLite 。这意味着,在每次操作之前,mutex都会锁定一个内部,以便数据库在读取时不写入,反之亦然。
"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)
Run Code Online (Sandbox Code Playgroud)
如上所示,在 100 次操作中,只偶尔需要真正的互斥锁。然而,为了保护这个小情况,我们必须为所有操作锁定它。
问题:有没有办法让“Thread_DB”在大部分时间都持有互斥锁,从而不需要每次锁定?只有当“Thread_Main”请求它时才会发生锁定/解锁。
SELECT在“Thread_DB”中排队。但是在运行多个 DB 的更大场景中,这会减慢响应速度并且不是实时的。不能让主线程等待它。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线程异步操作,由你决定)
| 归档时间: |
|
| 查看次数: |
221 次 |
| 最近记录: |