我必须使用线程进行一些银行账户转账并对不同结果进行基准测试。我认为同步解决方案与一般锁定的时间必须比每个帐户解决方案一个锁更糟。
这是我使用通用锁的实现:
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));
}
为什么普通锁定解决方案花费的时间少于第二个?
谢谢
锁定操作不是免费的。在第二个示例中,锁定/解锁操作的次数是第一个的两倍。其他操作似乎是简单的内存访问,所以它们不应该持续很长时间。
我的观点是,在您的系统中,您在锁中花费的时间多于实际处理中的时间,因此增加锁的数量是不相关的。如果transfer
像磁盘或网络那样使用慢速,那可能会有所不同。
顺便说一下,正如你在评论中所说的那样,400线程可能再次效率低于数量小得多。经验法则与您将使用的核心数量一样多,如果处理花费时间等待io,则可变因子增加 - 如果没有io从不超过可用核心。并且上限是所有线程使用的内存不得超过您要使用的内存,并且启动和同步线程的开销将远远低于总处理时间。