[OS] Operating System(7-2): Synchronization(Windows, Linux, POSIX)
๐ ์ด์์ฒด์ ์ ๊ณต ์์ ์ ๋ฆฌ
Kernel Synchronizatoin - Windows
- uniprocessor systems: Interrupt Mask๋ฅผ ์ฌ์ฉํ์ฌ global resource์ ๋ํ ์ ๊ทผ์ ๋ณดํธ
- Interrupt Mask: ํน์ ์ธํฐ๋ฝํธ์ ์ฒ๋ฆฌ๋ฅผ ์ผ์์ ์ผ๋ก ์ฐจ๋จ โ ์ค์ํ ์ฝ๋ ์น์ ์ด ๋ฐฉํด๋ฐ์ง ์๊ณ ์คํ๋จ
- multiple processor system: spinlock ์ฌ์ฉํ์ฌ global resource์ ๋ํ ์ ๊ทผ์ ๋ณดํธ
- spinlock: ๋ฝ์ ํ๋ํ ๋๊น์ง ๊ณ์ํด์ ํ์ธํ๋(spinning) ๋ฐฉ์์ ๋ฝ
- spinlock์ ๊ฐ์ง ์ค๋ ๋๋ never be preempted
- โ ํจ์จ์ฑ ๋๋ฌธ!: spinlock์ ๊ฐ์ง ์ค๋ ๋๊ฐ ์ ์ ๋๋ฉด deadlock์ด ๋ฐ์ํ ์ ์๋ค
Dispatcher Objects
- Dispatcher Objects: ์๋์ฐ๊ฐ ์ ๊ณตํ๋ ์ฌ์ฉ์ ๋ ๋ฒจ์์ ๋์ํ๋ ๊ฐ์ฒด(mutex, semaphore, events, timers)
mutex
: ์ํธ ๋ฐฐ์ ๋ฅผ ์ํ ๊ฐ์ฒดsemaphore
: ์ ํ๋ ์์ ๊ด๋ฆฌevents
: ์กฐ๊ฑด ๋ง์กฑ ์ ๊ธฐ๋ค๋ฆฌ๋ ์ค๋ ๋์๊ฒnotify()
timers
: ์๊ฐ์ด ๋ง๋ฃ๋๋ฉด ํ๋ ์ด์์ ์ค๋ ๋์notify()
dispatcher object๋ ๋ ๊ฐ์ ์ํ๊ฐ ์กด์ฌ:
- Signaled State: ๊ฐ์ฒด๊ฐ ์ฌ์ฉ ๊ฐ๋ฅํ ์ํ
- Non-signal State: ์ค๋ ๋๊ฐ ๋ธ๋ก๋๋ ์ํ
๊ฐ dispatcher object์๋ waiting queue๊ฐ ์กด์ฌ!
Object๊ฐ signaled-state๋ก ๋ฐ๋๋ฉด queue์ ๋๊ธฐํ๋ ๋ชจ๋ ์ค๋ ๋ ๋๋ ์ผ๋ถ๋ฅผ ๊นจ์ด๋ค
Mutex Dispatcher Object
์๋ ๋ฐฉ์:
- ์ค๋ ๋๊ฐ
mutex_lock
์ ํ๋ํ๋ฉด mutex๋ Non-signal state - ์์ ์ ์ค๋ ๋๊ฐ
mutex_lock
๋ฅผ ํด์ ํ๋ฉด Signal state - ๋ค๋ฅธ ์ค๋ ๋๊ฐ
mutex_lock
ํ๋ ๊ฐ๋ฅ
Linux Synchronization
2.6๋ฒ์ ์ด์ ์ ์ปค๋์์๋ disables interrupt๋ฅผ ์ฌ์ฉํด์ CS๋ฅผ ๊ตฌํ
โ 2.6์ดํ ๋ฒ์ :
- fully preemptive๋ฐฉ์ ์ฑํ
- ์ปค๋ ์ฝ๋ ์คํ ์ค์๋ ๋ ๋์ ์ฐ์ ์์์ ํ๋ก์ธ์ค๊ฐ ์์ผ๋ฉด ํ์ฌ ์คํ ์ค์ธ ํ๋ก์ธ์ค๋ฅผ ์ ์ ํ ์ ์์
Linux provides
- Semaphore
- ์์์ ๊ฐ์๋ฅผ ์นด์ดํ ํ์ฌ ์ ํ๋ ์์ ์ค๋ ๋๋ง ์์์ ์ ๊ทผ ๊ฐ๋ฅ
- Atomic Integers
- ์์์ ์ฐ์ฐ์ ์ง์ํ๋ ํน์ํ ์ ์ ํ์
(
atomic_t
)
- ์์์ ์ฐ์ฐ์ ์ง์ํ๋ ํน์ํ ์ ์ ํ์
(
- Spinlock
- ๋ฝ์ ํ๋ํ ๋๊น์ง ๊ณ์ํด์ ํ์ธํ๋(spinning) ๋ฐฉ์์ ๋ฝ
- Mutex Locks
- ์ํธ ๋ฐฐ์ (Mutual Exclusion)๋ฅผ ๊ตฌํํ๋ ๋ฝ
- ๋ฆฌ๋ ์ค์ ์คํ๋ฝ๊ณผ ๋ฎคํ ์ค ๋ฝ์ nonrecursive ํน์ฑ
โ ๋ฝ์ ์ด๋ฏธ ํ๋ํ ์ํ์์ ๋ค์ ํ๋ํ๋ ค๊ณ ํ๋ฉด ๋ฐ๋๋ฝ์ด ๋ฐ์ํ ์ ์์
- Single-CPU System: disabling kernel preemption ์ฌ์ฉ
- spinlock์ ๋จ์ผ CPU์์ ๋นํจ์จ์ ์ด๊ธฐ ๋๋ฌธ
- SMP(Symmetric Multi-Processing): spinlock ์ฌ์ฉ
- ์ฌ๋ฌ CPU๊ฐ ๋์์ ์์ ์ฒ๋ฆฌ๊ฐ ๋๊ธฐ ๋๋ฌธ์ spinlock ํจ์จ ํฅ์
- ์ปค๋์ ์๋ task๊ฐ lock ๊ฐ์ง๊ณ ์์ผ๋ฉด ์ด task๋ nonpreemptive
- preemptiveํ๋ฉด deadlock ๋ฐ์ ๊ฐ๋ฅ
- ํ์ฌ ๊ฐ์ง๊ณ ์๋ lock์ ์๋ฅผ
preempt_count
๋ผ๋ ๋ณ์์ ์ ์ฅ preempt_count
=0 ์ด๋ฉด preemption ๊ฐ๋ฅ!!
Atomic Variables
- atimic_t type:
1 2
atomic_t counter; int value;
atomic_init(_Atomic(T) *object, T value)
: ๋น์์์ ์ผ๋ก ์ด๊ธฐํT atomic_load(_Atomic(T) *object)
: ์์์ ์ผ๋ก ๊ฐ ์ฝ๊ธฐvoid atomic_store(_Atomic(T) *object, T desired)
: ์์์ ์ผ๋ก ๊ฐ ์ ์ฅT atomic_exchange(_Atomic(T) *object, T desired)
: ์์์ ์ผ๋ก ๊ฐ ๊ตํ_Bool atomic_compare_exchange_strong/_weak(_Atomic(T) *object, T *expected, T desired)
: ๋น๊ต ํ ๊ตํT atomic_fetch_add/_and/_or/_sub/_xor(_Atomic(T) *object, T operand)
: ์ฐ์ฐ ํ ์ด์ ๊ฐ ๋ฐํ
POSIX Synchronization
POSIX API๋ ๋ฉํฐ์ค๋ ๋ฉ ํ๋ก๊ทธ๋๋ฐ์ ์ํ ๋ค์ํ ๋๊ธฐํ ๋ฉ์ปค๋์ฆ์ ์ ๊ณต
POSIX Provides
- Mutex Locks: ์ํธ ๋ฐฐ์ ๋ฅผ ์ํ ๋ฝ
- Spin Locks: ์งง์ ๋๊ธฐ ์๊ฐ์ ์ํ ๋ฝ
- Semaphores: ์์ ์นด์ดํ ์ ์ํ ๋ฉ์ปค๋์ฆ
- Condition Variables: ํน์ s์กฐ๊ฑด์ด ์ถฉ์กฑ๋ ๋๊น์ง ์ค๋ ๋๋ฅผ ๋๊ธฐ์ํค๋ ๋ฉ์ปค๋์ฆ
์ฃผ์ ํจ์:
1
2
3
4
5
6
7
8
9
10
11
12
// ๋ฎคํ
์ค ์์ฑ ๋ฐ ํ๊ดด
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
// ์ ์ ์ด๊ธฐํ
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// ๋ฎคํ
์ค ์ ๊ธ ๋ฐ ํด์
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
๋ฎคํ ์ค ์ฌ์ฉ ์์
- ์์ฑ ๋ฐ ์ด๊ธฐํ:
1
2
3
4
5
6
#include <pthread.h>
pthread_mutex_t mutex;
/* ๋ฎคํ
์ค ๋ฝ ์์ฑ ๋ฐ ์ด๊ธฐํ */
pthread_mutex_init(&mutex, NULL);
- ํ๋ ๋ฐ ํด์ :
1
2
3
4
5
6
7
/* ๋ฎคํ
์ค ๋ฝ ํ๋ */
pthread_mutex_lock(&mutex);
/* ์๊ณ ์์ญ */
/* ๋ฎคํ
์ค ๋ฝ ํด์ */
pthread_mutex_unlock(&mutex);
POSIX Spinlock
- spinlock ์ฃผ์ ํจ์:
1
2
3
4
5
6
7
8
#include <pthread.h>
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
int pthread_spin_destroy(pthread_spinlock_t *lock);
int pthread_spin_lock(pthread_spinlock_t *lock);
int pthread_spin_trylock(pthread_spinlock_t *lock);
int pthread_spin_unlock(pthread_spinlock_t *lock);
int pshared
์์ pshared ์ต์ :- PTHREAD_PROCESS_PRIVATE: ํ๋ก์ธ์ค ๋ด ์ค๋ ๋๊ฐ ๊ณต์ (๊ธฐ๋ณธ๊ฐ)
- PTHREAD_PROCESS_SHARED: ํ๋ก์ธ์ค ์ธ ์ค๋ ๋๊ฐ ๊ณต์ (๋ฝ์ด ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์์ ์์ด์ผ ํจ)
POSIX Semaphore
POSIX๋ ๋ ๊ฐ์ง ๋ฒ์ ์ ์ธ๋งํฌ์ด ์ ๊ณต
- Named Semaphores
- ์๋ก ๊ด๋ จ ์๋ ํ๋ก์ธ์ค ๊ฐ์๋ ๊ณต์ ๊ฐ๋ฅ
- Unnamed Semaphores
- ๊ด๋ จ๋ ํ๋ก์ธ์ค(์: ๋ถ๋ชจ-์์) ๊ฐ์๋ง ๊ณต์ ๊ฐ๋ฅ
๊ณตํต ํจ์
sem_wait(sem_t *sem)
: ์ธ๋งํฌ์ด ๊ฐ์ ๊ฐ์์ํค๊ณ , ๊ฐ์ด 0์ด๋ฉด ๋ธ๋ก๋จ (P ์ฐ์ฐ)sem_post(sem_t *sem)
: ์ธ๋งํฌ์ด ๊ฐ์ ์ฆ๊ฐ์ํค๊ณ , ๋๊ธฐ ์ค์ธ ํ๋ก์ธ์ค ๊นจ์ (V ์ฐ์ฐ)sem_trywait(sem_t *sem)
: ๋น๋ธ๋กํน ๋ฐฉ์์ผ๋ก wait ์๋sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
: ์ ํ ์๊ฐ ๋ด์ wait ์๋sem_getvalue(sem_t *sem, int *sval)
: ํ์ฌ ์ธ๋งํฌ์ด ๊ฐ ์กฐํ
Named semaphore ํจ์
sem_t *sem_open(const char *name, int oflag)
: ๊ธฐ์กด ์ธ๋งํฌ์ด ์ด๊ธฐsem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value)
: ์ ์ธ๋งํฌ์ด ์์ฑ ๋ฐ ์ด๊ธฐํint sem_close(sem_t *sem)
: ์ธ๋งํฌ์ด ๋ซ๊ธฐ (ํ๋ก์ธ์ค์ ์ฐธ์กฐ๋ง ์ ๊ฑฐ)int sem_unlink(const char *name)
: ์ธ๋งํฌ์ด ์ด๋ฆ ์ ๊ฑฐ (๋ชจ๋ ์ฐธ์กฐ๊ฐ ๋ซํ๋ฉด ์ธ๋งํฌ์ด ํ๊ดด)
Unnamed semaphore ํจ์
int sem_init(sem_t *sem, int pshared, unsigned int value)
: ์ธ๋งํฌ์ด ์ด๊ธฐํint sem_destroy(sem_t *sem)
: ์ธ๋งํฌ์ด ํ๊ดด
Named Semaphores
Named Semaphores: ํ์ผ ์์คํ ๊ฒฝ๋ก๋ช ์ผ๋ก ์๋ณ๋๋ฉฐ, ๊ด๋ จ ์๋ ํ๋ก์ธ์ค ๊ฐ์๋ ๊ณต์ ๊ฐ๋ฅ
์์ฑ ๋ฐ ์ด๊ธฐํ:
1
2
3
4
5
#include <semaphore.h>
sem_t *sem;
/* ์ธ๋งํฌ์ด ์์ฑ ๋ฐ 1๋ก ์ด๊ธฐํ */
sem = sem_open("SEM", O_CREAT, 0666, 1);
SEM
: ์ธ๋งํฌ์ด ์ด๋ฆO_CREAT
: ์ธ๋งํฌ์ด๊ฐ ์์ผ๋ฉด ์์ฑ0666
: ์ ๊ทผ ๊ถํ (rw-rw-rw-)- rw ๊ถํ์ด ์์ด์ผ ๋ค๋ฅธ ํ๋ก์ธ์ค๊ฐ ์ฌ์ฉ ๊ฐ๋ฅ
1
: ์ด๊ธฐ ์ธ๋งํฌ์ด ๊ฐ- ํ๋ ๋ฐ ํด์ :
1
2
3
4
5
6
7
/* ์ธ๋งํฌ์ด ํ๋ */
sem_wait(sem);
/* ์๊ณ ์์ญ */
/* ์ธ๋งํฌ์ด ํด์ */
sem_post(sem);
Unnamed Semaphore
Unnamed Semaphore: ์ด๋ฆ์ด ์๊ณ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ก ์ฐธ์กฐ, ์ฃผ๋ก ๊ฐ์ ํ๋ก์ธ์ค ๋ด์ ์ค๋ ๋ ๊ฐ ๋๋ ๊ด๋ จ ํ๋ก์ธ์ค ๊ฐ(์: ๋ถ๋ชจ-์์)์ ์ฌ์ฉ
์์ฑ ๋ฐ ์ด๊ธฐํ:
1
2
3
4
5
#include <semaphore.h>
sem_t sem;
/* ์ธ๋งํฌ์ด ์์ฑ ๋ฐ 1๋ก ์ด๊ธฐํ */
sem_init(&sem, 0, 1);
&sem
: ์ธ๋งํฌ์ด ํฌ์ธํฐ0
: pshared ๊ฐ(๊ณต์ ๋ฒ์)0
: ๊ฐ์ ํ๋ก์ธ์ค ๋ด ์ค๋ ๋ ๊ฐ ๊ณต์Non-zero
: ํ๋ก์ธ์ค ๊ฐ ๊ณต์ (์ธ๋งํฌ์ด๊ฐ shared memory์ ์์ด์ผ ํจ)
1
: ์ด๊ธฐ ์ธ๋งํฌ์ด ๊ฐ- ํ๋ ๋ฐ ํด์ :
1
2
3
4
5
6
7
/* ์ธ๋งํฌ์ด ํ๋ */
sem_wait(&sem);
/* ์๊ณ ์์ญ */
/* ์ธ๋งํฌ์ด ํด์ */
sem_post(&sem);
POSIX Condition Variables
์กฐ๊ฑด ๋ณ์: ๋๊ธฐ์ด์ ์ด๋ฆ, ์ค๋ ๋๋ค์ ํน์ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋ ๋๊น์ง ์ด ๋๊ธฐ์ด์์ ๊ธฐ๋ค๋ฆฌ๊ณ , ์กฐ๊ฑด์ด ์ถฉ์กฑ๋๋ฉด ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์ ํธ๋ฅผ ๋ณด๋ด์ด ๋๊ธฐ ์ค์ธ ์ค๋ ๋๋ฅผ ๊นจ์ด
- POSIX๋ ์ผ๋ฐ์ ์ผ๋ก C/C++์์ ์ฌ์ฉ๋จ, C/C++ ์ธ์ด๋ Monitor ์ ๊ณต X
๊ทธ๋์ POSIX ์กฐ๊ฑด๋ณ์๋ mutual exclusion์ ์ํด POSIX mutex lock๊ณผ ๊ฐ์ด ์ฌ์ฉ๋๋ค
- ์ด๊ธฐํ ๋ฐ ํ๊ดด: ```c pthread_mutex_t mutex; pthread_cond_t cond_var;
// ๋์ ์ด๊ธฐํ pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond_var, NULL);
// ์ ์ ์ด๊ธฐํ pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
**์ฃผ์ ํจ์**:
* `pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex)`: ์กฐ๊ฑด์ด ์ถฉ์กฑ๋ ๋๊น์ง ๋๊ธฐ
* `pthread_cond_timedwait(...)`: ์ ํ ์๊ฐ ๋ด์์ ์กฐ๊ฑด ๋๊ธฐ
* `pthread_cond_signal(pthread_cond_t *cond)`: ๋๊ธฐ ์ค์ธ ์ค๋ ๋ ํ๋๋ฅผ ๊นจ์
* `pthread_cond_broadcast(pthread_cond_t *cond)`: ๋๊ธฐ ์ค์ธ ๋ชจ๋ ์ค๋ ๋๋ฅผ ๊นจ์
**์กฐ๊ฑด ๋ณ์ ์ฌ์ฉ ํจํด**:
* ์กฐ๊ฑด์ ๊ธฐ๋ค๋ฆฌ๋ ์ค๋ ๋ (a == b๊ฐ ๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆผ):
```c
pthread_mutex_lock(&mutex);
while (a != b) {
pthread_cond_wait(&cond_var, &mutex);
}
pthread_mutex_unlock(&mutex);
- release mutex lock:
pthread_cond_wait()
๋ ๋ฎคํ ์ค ๋ฝ์ ํ์ด์ฃผ๊ณ ๋๊ธฐ ์ํ ๋์ - wait on the condition variable: ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์ ํธ๋ฅผ ๋ณด๋ผ ๋๊น์ง ๋๊ธฐ
- ๊นจ์ด๋๋ฉด โ acquire mutex lock and return
โ
while ๋ฃจํ๋ฅผ ์ฌ์ฉํ๋ ์ด์ :
pthread_cond_wait()
๋ ๋ฎคํ
์ค ๋ฝ์ ํ๊ธฐ ๋๋ฌธ์ a๋ b์ ๊ฐ์ด ๋ณ๊ฒฝ๋ ์ ์์. ๋ฐ๋ผ์ while ๋ฃจํ๋ฅผ ์ฌ์ฉํ์ฌ ์กฐ๊ฑด์ ๋ค์ ๊ฒ์ฌํ๋ ๊ฒ์ด ๋งค์ฐ ์ค์
- ์กฐ๊ฑด์ ์ ํธํ๋ ์ค๋ ๋:
1 2 3 4
pthread_mutex_lock(&mutex); a = b; // ์กฐ๊ฑด์ ์ถฉ์กฑ์ํด pthread_cond_signal(&cond_var); pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond_var)
- ์กฐ๊ฑด๋ณ์์์ ๊ธฐ๋ค๋ฆฌ๊ณ ์๋ ์ค๋ ๋๊ฐ ์์ผ๋ฉด ๊นจ์ด๋์ด
- ์ด๋ ๊นจ์ด๋ ์ค๋ ๋๋ mutex lock์ ํ๋ํด์ผ ํ๋ฏ๋ก ์ด ์์ ์ ๊ฒฝ์ฐ ์์ง ์งํ์ด ์ ์ง๋ ์ํ
pthread_mutex_unlock(&mutex)
- a=b๋ฅผ ์ํํ๊ธฐ ์ํด ๊ฑธ์๋ lock์ signal์ ํธ์ถํ ํ unlock์ ํ๊ฒ๋๋ฉด, ๊นจ์ด๋ฌ์ง๋ง ์์ง ๋๊ธฐ์ํ์ ์๋ ์ค๋ ๋๊ฐ lock์ ํ๋ํ ํ ๋ค์์ ์งํํ ์ ์๋ค
- pthread_cond_signal vs pthread_cond_broadcast
pthread_cond_signal
: ํ๋์ ์์ ๋ง ์ฒ๋ฆฌํ๋ฉด ๋๋ ๊ฒฝ์ฐ ์ฌ์ฉ(์: ์์ฐ์-์๋น์์์ ํ๋์ ์์ดํ ๋ง ์ค๋น๋ ๊ฒฝ์ฐ) - ๋๊ธฐ ์ค์ธ ์ค๋ ๋ ํ๋๋ง ๊นจ์
- ์ด๋ค ์ค๋ ๋๊ฐ ๊นจ์ด๋ ์ง๋ ์์คํ ์ด ๊ฒฐ์
pthread_cond_broadcast
: ๋ชจ๋ ๋๊ธฐ ์ค์ธ ์ค๋ ๋๊ฐ ์กฐ๊ฑด์ ๋ค์ ํ์ธํด์ผ ํ๋ ๊ฒฝ์ฐ(์: ํ๋ก๊ทธ๋จ ์ข
๋ฃ ์ ํธ)
- ๋๊ธฐ ์ค์ธ ๋ชจ๋ ์ค๋ ๋๋ฅผ ๊นจ์
- ๋ชจ๋ ์ค๋ ๋๊ฐ ๋์์ ๋ฎคํ ์ค ๋ฝ์ ํ๋ํ๋ ค๊ณ ๊ฒฝ์
- ํ๋์ ์ค๋ ๋๋ง ๋ฝ์ ํ๋ํ๊ณ ๋๋จธ์ง๋ ๋ค์ ๋๊ธฐ์ํ
Alternative Approaches
์ ํต์ ์ธ ๋๊ธฐํ ๋ฉ์ปค๋์ฆ(๋ฎคํ ์ค, ์ธ๋งํฌ์ด, ์กฐ๊ฑด ๋ณ์) ์ธ์ ๋ณ๋ ฌ ํ๋ก๊ทธ๋๋ฐ์์ ์ฌ์ฉํ ์ ์๋ Alternative Approaches ์กด์ฌ
- Transactional Memory
- OpenMP
- Functional Programming Languages
Transactional Memory
- Transactional Memory: ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํธ๋์ญ์ ๊ฐ๋ ์ ๋ฉ๋ชจ๋ฆฌ ์ฐ์ฐ์ ์ ์ฉํ ๊ฒ, ์ฌ๋ฌ ๋ฉ๋ชจ๋ฆฌ ์ฝ๊ธฐ-์ฐ๊ธฐ ์ฐ์ฐ์ ํ๋์ ์์์ ๋จ์๋ก ๋ฌถ์ด์ ์ฒ๋ฆฌ
์ ํต์ ์ธ ๋ฐฉ์(๋ฎคํ ์ค):
1
2
3
4
5
void update() {
acquire(); // ๋ฎคํ
์ค ๋ฝ ํ๋
/* modify shared data */
release(); // ๋ฎคํ
์ค ๋ฝ ํด์
}
ํธ๋์ญ์ ๋ฉ๋ชจ๋ฆฌ:
1
2
3
4
5
void update() {
atomic {
/* modify shared data */
}
}
- ํธ๋์ญ์
์
atomic{S}
๊ตฌ๋ฌธ์ ์ถ๊ฐํ์ฌ ์์ฑํ ์ ์์ผ๋ฉฐ, ์ด๋ S ๋ด์ ๋ชจ๋ ์ฐ์ฐ์ด ์์์ ์ผ๋ก ์คํ๋๋๋ก ๋ณด์ฅ- ๋ชจ๋ ์ฐ์ฐ์ด ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌ๋์ด commit(ํ์ )๋๊ฑฐ๋
- ์ทจ์๋์ ์์ ์ผ๋ก ๋กค๋ฐฑํ๋ ๋ ๊ฐ์ง๋ง ๊ฐ๋ฅ
OpenMP
- OpenMP: ์ปดํ์ผ๋ฌ ์ง์๋ฌธ๊ณผ API๋ฅผ ํตํด ๋ณ๋ ฌ ํ๋ก๊ทธ๋๋ฐ์ ์ง์, ๊ธฐ์กด์ ์์ฐจ ์ฝ๋๋ฅผ ๊ฐ๋จํ ์ง์๋ฌธ ์ถ๊ฐ๋ง์ผ๋ก ๋ณ๋ ฌํํ ์ ์์ด ๋งค์ฐ ์ค์ฉ์
์ฃผ์ ์ง์๋ฌธ:
1
2
3
4
5
6
7
8
9
#pragma omp parallel // ์ฝ์ด์ ์๋งํผ ์ค๋ ๋ ์์ฑ ํ, ๋ณ๋ ฌ๋ก ์คํํ๋ผ
{
void update(int value) {
#pragma omp critical // Atomically ์คํํ๋ผ
{
count += value;
}
}
}
#pragma omp parallel
: ์ฌ์ฉ ๊ฐ๋ฅํ ์ฝ์ด ์๋งํผ ์ค๋ ๋๋ฅผ ์์ฑํ์ฌ ๋ณ๋ ฌ๋ก ์คํ#pragma omp critical
: ํฌํจ๋ ์ฝ๋ ๋ธ๋ก์ ์๊ณ ์์ญ์ผ๋ก ์ฒ๋ฆฌํ์ฌ ์์์ ์ผ๋ก ์คํ