...
Code Block | ||
---|---|---|
| ||
typedef struct {
int balance;
pthread_mutex_t balance_mutex;
} bank_account;
typedef struct {
bank_account *from;
bank_account *to;
int amount;
} deposit_thr_args;
void create_bank_account(bank_account **ba, int initial_amount) {
int result;
bank_account *nba = malloc(sizeof(bank_account));
if (nba == NULL) {
/* Handle Error */
}
nba->balance = initial_amount;
result = pthread_mutex_init(&nba->balance_mutex, NULL);
if (result) {
/* Handle Error */
}
*ba = nba;
}
void *deposit(void *ptr) {
int result;
deposit_thr_args *args = (deposit_thr_args *)ptr;
if ((result = pthread_mutex_lock(&(args->from->balance_mutex))) != 0) {
/* Handle Error */
}
/* not enough balance to transfer */
if (args->from->balance < args->amount) {
if ((result = pthread_mutex_unlock(&(args->from->balance_mutex))) != 0) {
/* Handle Error */
}
return NULL;
}
if ((result = pthread_mutex_lock(&(args->to->balance_mutex))) != 0) {
/* Handle Error */
}
args->from->balance -= args->amount;
args->to->balance += args->amount;
if ((result = pthread_mutex_unlock(&(args->from->balance_mutex))) != 0) {
/* Handle Error */
}
if ((result = pthread_mutex_unlock(&(args->to->balance_mutex))) != 0) {
/* Handle Error */
}
free(ptr);
return NULL;
}
int main(void) {
pthread_t thr1, thr2;
int result;
bank_account *ba1;
bank_account *ba2;
create_bank_account(&ba1, 1000);
create_bank_account(&ba2, 1000);
deposit_thr_args *arg1 = malloc(sizeof(deposit_thr_args));
if (arg1 == NULL) {
/* Handle Error */
}
deposit_thr_args *arg2 = malloc(sizeof(deposit_thr_args));
if (arg2 == NULL) {
/* Handle Error */
}
arg1->from = ba1;
arg1->to = ba2;
arg1->amount = 100;
arg2->from = ba2;
arg2->to = ba1;
arg2->amount = 100;
/* perform the deposits */
if ((result = pthread_create(&thr1, NULL, deposit, (void *)arg1)) != 0) {
/* Handle Error */
}
if ((result = pthread_create(&thr2, NULL, deposit, (void *)arg2)) != 0) {
/* Handle Error */
}
pthread_exit(NULL);
return 0;
}
|
...
Code Block | ||
---|---|---|
| ||
typedef struct { int balance; pthread_mutex_t balance_mutex; unsigned int id; /* should never be changed after initialized */ } bank_account; unsigned int global_id = 1; void create_bank_account(bank_account **ba, int initial_amount) { int result; bank_account *nba = malloc(sizeof(bank_account)); if (nba == NULL) { /* Handle Error */ } nba->balance = initial_amount; result = pthread_mutex_init(&nba->balance_mutex, NULL); if (result != 0) { /* Handle Error */ } nba->id = global_id++; *ba = nba; } void *deposit(void *ptr) { deposit_thr_args *args = (deposit_thr_args *)ptr; int result; if (args->from->id == args->to->id) return; /* ensure proper ordering for locking */ if (args->from->id < args->to->id) { if ((result = pthread_mutex_lock(&(args->from->balance_mutex))) != 0) { /* Handle Error */ } if ((result = pthread_mutex_lock(&(args->to->balance_mutex))) != 0) { /* Handle Error */ } } else { if ((result = pthread_mutex_lock(&(args->to->balance_mutex))) != 0) { /* Handle Error */ } if ((result = pthread_mutex_lock(&(args->from->balance_mutex))) != 0) { /* Handle Error */ } } /* not enough balance to transfer */ if (args->from->balance < args->amount) { if ((result = pthread_mutex_unlock(&(args->from->balance_mutex))) != 0) { /* Handle Error */ } if ((result = pthread_mutex_unlock(&(args->to->balance_mutex))) != 0) { /* Handle Error */ } return; } args->from->balance -= args->amount; args->to->balance += args->amount; if ((result = pthread_mutex_unlock(&(args->from->balance_mutex))) != 0) { /* Handle Error */ } if ((result = pthread_mutex_unlock(&(args->to->balance_mutex))) != 0) { /* Handle Error */ } free(ptr); return; } |
...
Wiki Markup |
---|
\[[Barney 2010|AA. Bibliography#Barney 10]\] [pthread_mutex tutorial|https://computing.llnl.gov/tutorials/pthreads/#Mutexes]
\[[Bryant 2003|AA. Bibliography#Bryant 03]\] Chapter 13, Concurrent Programming |
...
14. Concurrency (CON) 49. Miscellaneous (MSC)CON36-C. Do not perform operations that can block while holding a lock