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