2015-01-10 3 views
-5

Итак, предположим, что у меня есть два банковских счета A и B, и мне нужно атомизировать перевод денег. установочном является следующее: `Как написать функцию передачи учетной записи атома

struct account{ 
    int64 amount; 
    pthread_mutex_lock m; 
} 

`

вот мой подход: `

bool Transfer(int from_account, int to_account, int64 amount) 
{ 
    pthread_lock(&account[from_account].m); 
    bool ret = false; 
    if(accounts[from_account].balance>=amount) 
    { 
     accounts[from_account].balance-=amount; 
     ret = true; 
    } 
    pthread_unlock(&account[from_account].m); 
    pthread_lock(&account[to_account].m); 
    accounts[to_account].balance+=amount; 
    pthread_unlock(&account[to_account].m); 
    return ret; 
} 

`

передача функции денег из from_account в to_account, возвратите bool, только передайте, оставив деньги на счете> = количество. Является ли эта функция подходящей? Я предполагаю, что это не вызовет проблему взаимоблокировки, но разве она не делает всю функцию неатомной? Так могут быть условия гонки? Пожалуйста, помогите мне, спасибо большое.

+2

Эта функция не является атомарной. И есть условия гонки. И есть сценарии взаимоблокировки. И это не исключение. Итак, нет. Это нехороший подход. –

+1

Пожалуйста, задайте конкретный вопрос. Кроме того, какая платформа? –

+0

_ @ user3799934_ Считаете ли вы использование [потока стандартов стандартов и поддержки синхронизации] (http://en.cppreference.com/w/cpp/thread), вместо того, чтобы бороться с 'pthread' изначально? –

ответ

0

Ваш код логически сломан. Независимо от баланса from_account, to_account победит account безоговорочно! (и я хочу быть владельцем_потока :)

В этом случае вы должны приобрести как блокировки двух учетных записей, так и вызвать потенциальную проблему взаимоблокировки.

Самый простой способ избежать тупиковой ситуации - обеспечить соблюдение порядка захвата блокировки, например, первая учетная запись с меньшим индексом.

bool Transfer(int from_account, int to_account, int64 amount) 
{ 
    // acquire locks (in pre-defined order) 
    if (from_account < to_account) 
    { 
    pthread_lock(&accounts[from_account].m); 
    pthread_lock(&accounts[to_account].m); 
    } else { 
    pthread_lock(&accounts[to_account].m); 
    pthread_lock(&accounts[from_account].m); 
    } 
    // transfer amount 
    bool ret = false; 
    if (accounts[from_account].balance >= amount) 
    { 
    accounts[from_account].balance -= amount; 
    accounts[to_account].balance += amount; 
    ret = true; 
    } 
    // release both locks 
    pthread_unlock(&accounts[from_account].m); 
    pthread_unlock(&accounts[to_account].m); 
    return ret; 
} 
Смежные вопросы