2개의 프로그램이 공유 메모리에 더하는 연산을 동시에 실행한다.
프로그램1은 Pthread를 사용해 2개의 스레드를 만들고 2개의 스레드가 각각 10,000 번의 루프를 돌면서 공유 메모리에 1씩 더하는 연산을 수행
프로그램2는 10,000번의 루프를 돌면서 공유 메모리에 1씩 더하는 연산을 수행
프로그램은 ./pro1 & ./pro2로 동시에 실행되며, 최종적으로 공유 메모리에 30,000이 저장되어야 한다.
[pro1.c]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>
#define SHM_KEY 1234
int *shared_memory; //포인터로 변경
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //뮤텍스 초기화
//두 개의 스레드를 생성하여 실행
void* thread_function(void* arg) {
for (int i = 0; i < 10000; ++i) {
pthread_mutex_lock(&mutex); //뮤텍스 락
(*shared_memory)++; //포인터로 참조하여 값 증가, 임계영역
pthread_mutex_unlock(&mutex); //뮤텍스 언락
}
return NULL;
}
int main() {
int shmid; //공유 메모리 식별자
//공유메모리 생성
shmid = shmget(SHM_KEY, sizeof(int), IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget");
return 1;
}
//공유 메모리에 접근
shared_memory = (int *)shmat(shmid, NULL, 0);
if (shared_memory == (int *)-1) {
perror("shmat");
return 1;
}
pthread_t threads[2];
for (int i = 0; i < 2; ++i) {
pthread_create(&threads[i], NULL, thread_function, NULL);
}
for (int i = 0; i < 2; ++i) {
pthread_join(threads[i], NULL);
}
printf("Final shared memory pro1: %d\n", *shared_memory);
pthread_mutex_destroy(&mutex);
shmdt(shared_memory); //공유 메모리 분리
shmctl(shmid, IPC_RMID, NULL); //공유 메모리 삭제
return 0;
}
프로그램 1은 스레드 2개를 사용하고 각 스레드가 공유 메모리에 1씩 더하는 작업을 수행하며, 10000번 루프를 실행한다. 프로그램 1에서 공유 메모리에 저장하는 값은 20000이다. 위 코드는 루프를 통해 10000번 반복하면서 뮤텍스를 사용하여 임계 영역으로 진입한다. ‘(*shared_memory)++’는 공유 메모리에 접근하여 값을 증가시키기 때문에 임계 영역이다. 이 부 분은 여러 스레드나 프로세스에서 동시에 실행될 경우, 공유 메모리에 대한 일관성을 해치지 않 기 위해 하나의 스레드만 접근해야 한다. 따라서 뮤텍스를 사용하여 상호 배제를 구현했다. 뮤텍 스를 사용하여 임계 영역에 진입하면 다른 스레드는 해당 뮤텍스를 획득할 때까지 대기한다. ‘pthread_mutex_lock’을 호출하여 뮤텍스를 획득할 수 있고 뮤텍스를 획득한 스레드만 공유 메모 리에 접근할 수 있다. ‘pthread_mutex_unlock’을 호출하여 뮤텍스를 해제한다. 뮤텍스를 해체해야 다른 스레드나 프로세스가 임계 영역에 접근할 수 있다.
[pro2.c]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>
#define SHM_KEY 1234
int main() {
int shmid;
int *shared_memory;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //뮤텍스 초기화
//공유메모리 생성
shmid = shmget(SHM_KEY, sizeof(int), 0666);
if (shmid == -1) {
perror("shmget");
return 1;
}
//공유 메모리에 접근
shared_memory = (int *)shmat(shmid, NULL, 0);
if (shared_memory == (int *)-1) {
perror("shmat");
return 1;
}
for (int i = 0; i < 10000; ++i) {
pthread_mutex_lock(&mutex); //뮤텍스 락
(*shared_memory)++; //임계영역
pthread_mutex_unlock(&mutex); //뮤텍스 언락
}
printf("Final shared memory Pro2: %d\n", *shared_memory);
pthread_mutex_destroy(&mutex);
shmdt(shared_memory); //공유 메모리 분리
shmctl(shmid, IPC_RMID, NULL); //공유 메모리 삭제
return 0;
}
프로그램 2는 공유 메모리에 1씩 더하는 작업을 수행하며, 10000번의 루프를 실행한다. 프로그램 1과 마찬가지로 ‘(*shared_memory)++’는 임계 영역이다. 여러 프로세스나 스레드가 동 시에 접근하면 문제가 발생하기 때문에 뮤텍스를 사용했다. ‘pthread_mutex_lock’과 ‘pthread_mutex_unlock’을 사용하여 하나의 프로세스만 임계 영역에 접근할 수 있도록 했다. 따라 서 공유 메모리의 일관성과 정확성을 유지할 수 있다. 또한 ‘shmget’과 ‘shmat’을 사용하여 공유 메모리를 설정하고 접근한다. ‘pthread_mutex_t’를 초기 화하여 상호 배제를 위한 뮤텍스를 생성하고 for문 내부에 뮤텍스 락과 뮤텍스 언락을 사용하여 임계 영역을 설정한다. ‘pthread_mutex_destroy’, ‘shmdt’, ‘shmctl’ 등을 사용하여 뮤텍스 해제 및 공 유 메모리 제거도 수행하였다.
[실행결과]
프로그램 2에서 10000번 루프를 돌아 공유 메모리에 10000이 저장되었고, 프로그램 1에서는 스 레드 2개가 각각 10000번 루프를 돌아 20000이 저장되었다. 따라서 최종적으로 공유 메모리에 저장된 값이 30000인 것을 확인했다