Банковский перевод с потоками
Я должен сделать несколько банковских переводов с потоками и сравнительный анализ различных результатов. Я думаю, что время синхронизированного решения с общей блокировкой должно быть хуже, чем одна блокировка для решения учетной записи.
Вот моя реализация с общей блокировкой:
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));
}
Почему решение общей блокировки тратит меньше времени, чем второе?
Спасибо
1 ответ
Операция блокировки не является бесплатной. Во втором примере вы выполняете вдвое больше операций блокировки / разблокировки, чем в первом. Другие операции кажутся простыми обращениями к памяти, поэтому они не должны длиться очень долго.
Мое мнение таково, что в вашей системе вы проводите больше времени в блокировках, чем в реальной обработке, поэтому увеличение количества блокировок не имеет значения. Это может быть иначе, если transfer
используется медленно, как диск или сеть.
Кстати, как вы сказали в комментарии, 400 потоков, вероятно, снова менее эффективны, чем гораздо меньшее число. Эмпирическое правило равно количеству ядер, которое вы будете использовать, увеличенное на переменный коэффициент, если обработка тратит время на ожидание ввода-вывода - если нет ввода-вывода, то никогда больше, чем доступные ядра. И верхний предел состоит в том, что объем памяти, используемой всеми потоками, не должен превышать объем памяти, который вы хотите использовать, и что накладные расходы на запуск и синхронизацию потоков остаются намного ниже, чем общее время обработки.