bank_account.c

Download
c 150 lines 3.6 KB
  1// bank_account.c
  2// 뮤텍스를 이용한 스레드 안전 은행 계좌
  3#include <stdio.h>
  4#include <stdlib.h>
  5#include <pthread.h>
  6#include <unistd.h>
  7#include <time.h>
  8
  9typedef struct {
 10    int balance;
 11    pthread_mutex_t lock;
 12} Account;
 13
 14Account* account_create(int initial_balance) {
 15    Account* acc = malloc(sizeof(Account));
 16    acc->balance = initial_balance;
 17    pthread_mutex_init(&acc->lock, NULL);
 18    return acc;
 19}
 20
 21void account_destroy(Account* acc) {
 22    pthread_mutex_destroy(&acc->lock);
 23    free(acc);
 24}
 25
 26int account_deposit(Account* acc, int amount) {
 27    pthread_mutex_lock(&acc->lock);
 28
 29    acc->balance += amount;
 30    int new_balance = acc->balance;
 31
 32    pthread_mutex_unlock(&acc->lock);
 33    return new_balance;
 34}
 35
 36int account_withdraw(Account* acc, int amount) {
 37    pthread_mutex_lock(&acc->lock);
 38
 39    if (acc->balance >= amount) {
 40        acc->balance -= amount;
 41        int new_balance = acc->balance;
 42        pthread_mutex_unlock(&acc->lock);
 43        return new_balance;
 44    }
 45
 46    pthread_mutex_unlock(&acc->lock);
 47    return -1;  // 잔액 부족
 48}
 49
 50int account_get_balance(Account* acc) {
 51    pthread_mutex_lock(&acc->lock);
 52    int balance = acc->balance;
 53    pthread_mutex_unlock(&acc->lock);
 54    return balance;
 55}
 56
 57// 이체 (두 계좌 간)
 58int account_transfer(Account* from, Account* to, int amount) {
 59    // 데드락 방지: 항상 같은 순서로 잠금
 60    // 주소값이 작은 계좌 먼저 잠금
 61    Account* first = (from < to) ? from : to;
 62    Account* second = (from < to) ? to : from;
 63
 64    pthread_mutex_lock(&first->lock);
 65    pthread_mutex_lock(&second->lock);
 66
 67    int result = -1;
 68    if (from->balance >= amount) {
 69        from->balance -= amount;
 70        to->balance += amount;
 71        result = from->balance;
 72    }
 73
 74    pthread_mutex_unlock(&second->lock);
 75    pthread_mutex_unlock(&first->lock);
 76
 77    return result;
 78}
 79
 80// 테스트용 스레드 데이터
 81typedef struct {
 82    Account* acc;
 83    int thread_id;
 84} ThreadArg;
 85
 86void* depositor(void* arg) {
 87    ThreadArg* ta = (ThreadArg*)arg;
 88
 89    for (int i = 0; i < 100; i++) {
 90        int new_balance = account_deposit(ta->acc, 100);
 91        printf("[입금자 %d] 입금 100원 -> 잔액: %d\n", ta->thread_id, new_balance);
 92        usleep(rand() % 10000);
 93    }
 94
 95    return NULL;
 96}
 97
 98void* withdrawer(void* arg) {
 99    ThreadArg* ta = (ThreadArg*)arg;
100
101    for (int i = 0; i < 100; i++) {
102        int result = account_withdraw(ta->acc, 100);
103        if (result >= 0) {
104            printf("[출금자 %d] 출금 100원 -> 잔액: %d\n", ta->thread_id, result);
105        } else {
106            printf("[출금자 %d] 잔액 부족\n", ta->thread_id);
107        }
108        usleep(rand() % 10000);
109    }
110
111    return NULL;
112}
113
114int main(void) {
115    srand(time(NULL));
116
117    Account* acc = account_create(10000);
118    printf("초기 잔액: %d\n\n", account_get_balance(acc));
119
120    pthread_t depositors[3];
121    pthread_t withdrawers[3];
122    ThreadArg args[6];
123
124    // 입금자 3명
125    for (int i = 0; i < 3; i++) {
126        args[i].acc = acc;
127        args[i].thread_id = i;
128        pthread_create(&depositors[i], NULL, depositor, &args[i]);
129    }
130
131    // 출금자 3명
132    for (int i = 0; i < 3; i++) {
133        args[i + 3].acc = acc;
134        args[i + 3].thread_id = i;
135        pthread_create(&withdrawers[i], NULL, withdrawer, &args[i + 3]);
136    }
137
138    // 대기
139    for (int i = 0; i < 3; i++) {
140        pthread_join(depositors[i], NULL);
141        pthread_join(withdrawers[i], NULL);
142    }
143
144    printf("\n최종 잔액: %d\n", account_get_balance(acc));
145    printf("예상 잔액: %d (초기 10000 + 입금 30000 - 출금 최대 30000)\n", 10000);
146
147    account_destroy(acc);
148    return 0;
149}