我必须通过线程进行一些银行帐户转移,并基准测试不同的结果。我认为与一般锁相结合的解决方案的时间必须比每个帐户解决方案一个锁定。
这是我的常规锁的实现:
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
使用慢速IO(例如磁盘或网络),则可能会有所不同。
顺便说一句,正如您在评论中所说的那样,400个线程的效率可能不如数量少得多。一条经验法则与您将使用的核心数量一样多,如果处理花费时间等待IO,则增加了一个可变因素 - 如果没有IO的核心,则不超过可用的内核。上限是所有线程使用的内存不得超过您要使用的内存,并且启动和同步线程的开销保持比总处理时间要低得多。