c - 使用线程进行银行账户转账

标签 c transfer account locks bank

我必须使用线程进行一些银行帐户转账并对不同结果进行基准测试。我认为普通锁的同步方案的时间肯定比一账户一锁的方案差。

这是我使用通用锁的实现:

pthread_mutex_t general_mutex;

typedef struct {
    int id;
    double balance;
} Account;

int NThreads = 400; /*Threads number*/

#define N 20             /*Accounts number*/
Account accounts[N];
void transfer(double money, Account* origin, Account* destini) {

    pthread_mutex_lock(&general_mutex); //Init general lock.

    bool wasPosible = withdraw(origin, money);
    if (wasPosible ) deposit(destini, money);

    pthread_mutex_unlock(&general_mutex); //End general lock.
}

以下是每个帐户单独锁定的实现:

typedef struct {
    int id;
    double balance;
    pthread_mutex_t mutex; // lock to use/modify vars
} Account;

int NThreads = 400; /*Threads number*/

#define N 20             /*Accounts number*/
Account accounts[N];
void transfer(double money, Account* origin, Account* destini) {

    if (from->id < to->id) {
         pthread_mutex_lock(&(origin->mutex));
         pthread_mutex_lock(&(destini->mutex));
    } else {
         pthread_mutex_lock(&(destini->mutex));
         pthread_mutex_lock(&(origin->mutex));
    }

    bool wasPosible = withdraw(origin, money);
    if (wasPosible ) deposit(destini, amount);

    pthread_mutex_unlock(&(origin->mutex));
    pthread_mutex_unlock(&(destini->mutex));
}

为什么一般的锁方案比第二种方案花费的时间更少?

谢谢

最佳答案

锁定操作不是免费的。在第二个示例中,您执行的锁定/解锁操作是第一个示例的两倍。其他操作似乎都是简单的内存访问,因此它们不会持续很长时间。

我的观点是,在您的系统中,您在锁上花费的时间比实际处理的时间多,因此增加锁的数量并不相关。如果传输使用磁盘或网络等慢速IO,情况可能会有所不同。

顺便说一句,正如您在评论中所说,400 个线程的效率可能再次低于小得多的数量。经验法则是与您将使用的核心数量一样多,如果处理花费时间等待 io,则增加一个可变因子 - 如果没有 io 永远不会超过可用核心。上限是所有线程使用的内存不得超过您想要使用的内存,并且启动和同步线程的开销远低于总处理时间。

关于c - 使用线程进行银行账户转账,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54921634/

相关文章:

c - GCC 内联汇编 - 在调用之前将 float 移动到 XMM0

c - 创建字符串数组时遇到问题。我究竟做错了什么?

c++ - std::pow 给出分数指数的错误近似值

javascript - 尝试使用 javascript 在我的页面上创建一个 javascript 帐户系统......但显然我忽略了一些东西

react-native - 华为帐号登录: Scope email address option getting as unselected

c - 类型转换指针取消引用

ios - View Controller 之间的 Swift 传输数据保持为空

mysql - 将旧的 3.23.49 MySQL 数据库转移到 5.0.51 MySQL 数据库 - 以 ANSI 和 UTF-8 编码

Java 禁用 JTree/TransferHandler 的剪切操作

shell - if 语句 shell 脚本中的多个条件