如何为一组 pthread 共享互斥锁?

Posted

技术标签:

【中文标题】如何为一组 pthread 共享互斥锁?【英文标题】:how to share a mutex lock for a group of pthreads ? 【发布时间】:2011-12-28 08:46:30 【问题描述】:

我正在尝试用 pthread 做一些事情并同步它们: 我怎么能只对一组线程使用互斥锁? 假设我有 t0,t1, t2, .. t20。 pthreads 同时运行,我想为偶数线程锁一个锁,为奇数线程锁一个锁......或者前十个锁一个锁,其余锁另一个,或者一个锁定每个。我的意思是,根据数据对 pthread 进行分组(此函数中的第四个参数:

int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);

并为一组 pthread 共享互斥锁。

我正在从事一种银行项目,我想锁定所有试图访问同一个帐号的 preads。 (作为关键部分 CRUD 操作) 是否有意义 ?还是有更好的方法来做到这一点? 提前感谢您的帮助和时间;)

J.

【问题讨论】:

我刚想到一个类似的问题,不确定它是否与银行账户有关,但您可能想检查一下:***.com/questions/18493241/… 【参考方案1】:

互斥信号量并不是要绑定到特定线程,而是要保护特定的资源。

在您的情况下,该资源是银行帐户。我不相信每个账户互斥的解决方案是可行的,特别是如果您的银行拥有数千万客户,就像一些中国银行那样:-)

一种更可行的方法可能是将当前正在处理的帐户列表保存在内存中,并使用 single utex 来保护它。然后这些操作将锁定互斥锁,检查并可能修改列表,然后解锁互斥锁。

您正在寻找的更好的方法是使用 ACID 类型的后备存储(如数据库)来确保所有更新都是原子的。

【讨论】:

+1 用于建议支持 ACID 的后备存储。帐户列表和单个互斥锁并非没有额外的工作。您需要学习条件变量以避免忙于等待您的帐户解锁。 嗨@paxdiablo,感谢您的回答。你的意思是所有账户都有一份清单?所以互斥锁将保护这个列表,任何操作都必须在继续之前检查该列表。但是如果我希望线程同时在不同的帐户上工作,这是一个帐户列表? @jcosta,您在处理帐户时不会锁定互斥锁,而是在处理列表时锁定它。示例:一个线程想要在帐户 #7 上工作。它锁定列表,然后检查以确保没有其他人在处理它。如果是其他人,它会解锁互斥锁和错误。如果不是,它会声明该帐户的所有权(存储其线程 ID),解锁互斥锁并开始工作。完成后,它会锁定、删除所有权并解锁。互斥锁仅在列表本身更新期间保留,因此不同的线程可以在不同的帐户上工作。 @paxdiablo: 而不是“如果其他人正在[使用该帐户],它会解锁互斥锁和错误”您可能想要“直到帐户可用,等待条件变量”(只要线程放弃帐户所有权,就会发出条件变量信号)。 谢谢你们。我会尝试这些方法。 @caf 当您说等待时,您的意思是 pthread_cond_wait() 吗?将锁定和解锁互斥锁的相同线程也将控制条件,不是吗?还是其他线程的条件?再次感谢。【参考方案2】:

决定哪些线程共享一个给定的互斥锁。如果您想要一个仅由偶数线程共享的互斥锁,那么您所要做的就是确保该互斥锁仅由偶数线程访问。

话虽如此,使用互斥锁的正确方法通常是将它与一组给定的数据相关联,而不是一组特定的代码。在您的帐号情况下,您可以为每个帐户对象创建一个互斥锁,并确保访问帐户的任何线程首先锁定相应的互斥锁(并在完成时将其解锁)。

【讨论】:

感谢@caf,明白了,但是如何为每个银行账户实现一个互斥锁?我的意思是,互斥锁是一个变量:线程之间共享的 pthread_mutex_t ..所以你的意思是每个帐户添加一个变量? (再次,对不起,如果这是一个菜鸟问题) @jcosta:是的——例如,如果您已经有一个代表单个银行账户的struct,您可以将pthread_mutex_t 添加到该struct。您需要在首次创建 struct 时(以及在其他线程可见之前)使用 pthread_mutex_init() 对其进行初始化,并在释放 struct 时使用 pthread_mutex_destroy() 将其拆除。【参考方案3】:

一般来说,您不会锁定线程 - 您会锁定数据结构,其中任何/所有想要访问该数据结构的线程都必须获取数据结构的互斥锁。

对于您的情况,这意味着每个银行帐户一个互斥锁。

下一个问题是有些东西需要访问多个数据结构。例如,将 100 美元从一个帐户转移到另一个帐户(您想锁定两个帐户,然后减少第一个帐户的余额并增加第二个帐户的余额,然后释放两个锁定)。这可能导致死锁。例如,如果一个线程想要锁定 A 然后 B,而另一个线程想要锁定 B 然后 A;那么第一个线程可能会锁定 A,而第二个线程可能会锁定 B,然后两个线程都无法获得他们需要的第二个锁定。

该问题的解决方案是拥有一个全局“锁定顺序”,并且仅按该顺序获取锁定。

对于您的情况,您有帐号。如果一个线程想要锁定 2 个或更多帐户,那么它会确定哪些帐户,然后对帐户列表进行排序(例如,从最低帐号到最高帐号),然后按该顺序获取它需要的所有锁。一旦线程获得了它需要的所有锁,它就会做它必须做的任何事情,然后以相反的顺序释放它获得的所有锁。

【讨论】:

嗨@Brendan,谢谢,是的,您使用锁定顺序来防止死锁是对的。我会这样做。但是如何为每个银行账户实现一个互斥锁呢?我的意思是,互斥锁是一个变量:pthread_mutex_t 在线程之间共享..所以您的意思是每个帐户添加一个变量? (对不起,如果这是一个菜鸟问题)

以上是关于如何为一组 pthread 共享互斥锁?的主要内容,如果未能解决你的问题,请参考以下文章

(转载)pThreads线程 线程同步--互斥量/锁

pthread mutex 进程间互斥锁

为啥 pthread 的条件变量函数需要互斥锁?

互斥锁- pthread_mutex

自旋锁和互斥锁的区别

PTHREAD 互斥锁是只避免同时访问资源,还是做更多的事情?