pthreads (tsz. pthreadses)
pthread
(POSIX thread) használatával programjaink több szálat hozhatnak létre, amelyek együtt, párhuzamosan futnak, és megoszthatják a memóriát.
A pthread
API funkciói pthread_
prefix-szel kezdődnek.
Funkció | Leírás |
---|---|
pthread_create
|
új szál létrehozása |
pthread_join
|
szál befejezésének megvárása |
pthread_exit
|
szál befejezése |
pthread_mutex_*
|
mutex kezelés (zárolás) |
pthread_cond_*
|
feltételes változók |
pthread_detach
|
szál „leválasztása” (nem kell join -olni)
|
#include <pthread.h>
#include <stdio.h>
void* hello(void* arg) {
printf("Hello from thread!\n");
return NULL;
}
int main() {
pthread_t t1;
pthread_create(&t1, NULL, hello, NULL);
pthread_join(t1, NULL);
return 0;
}
pthread_create
: létrehoz egy új szálat, amely a hello()
függvényt futtatjapthread_join
: megvárja, amíg a szál befejeződik
Ha több szál megosztott változókat módosít, versenyhelyzet (race condition) léphet fel. A mutex (mutual exclusion) egy zárolási mechanizmus, amely biztosítja, hogy egyszerre csak egy szál férhessen hozzá a kritikus szakaszhoz.
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void* increment(void* arg) {
pthread_mutex_lock(&lock);
// kritikus szakasz
counter++;
pthread_mutex_unlock(&lock);
return NULL;
}
#include <pthread.h>
#include <stdio.h>
int counter = 0;
pthread_mutex_t lock;
void* worker(void* arg) {
for (int i = 0; i < 10000; ++i) {
pthread_mutex_lock(&lock);
counter++;
pthread_mutex_unlock(&lock);
}
return NULL;
}
int main() {
pthread_t t1, t2;
pthread_mutex_init(&lock, NULL);
pthread_create(&t1, NULL, worker, NULL);
pthread_create(&t2, NULL, worker, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("Final counter: %d\n", counter);
pthread_mutex_destroy(&lock);
return 0;
}
Kimenet: garantáltan 20000
, mert a mutex védi az increment
műveletet.
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void *),
void *arg);
thread
: ide kerül a szál-azonosítóattr
: attribútum (általában NULL)start_routine
: a függvény, amit a szál futtatarg
: argumentum a függvényhez (void*)
int pthread_join(pthread_t thread, void **retval);
thread
szál végétretval
: a visszatérési érték (ha kell)
A pthread_cond_t
lehetővé teszi, hogy egy szál várjon bizonyos feltételre, és egy másik szál felébressze:
pthread_mutex_t mutex;
pthread_cond_t cond;
bool ready = false;
void* waiter(void* arg) {
pthread_mutex_lock(&mutex);
while (!ready)
pthread_cond_wait(&cond, &mutex);
printf("Ready!\n");
pthread_mutex_unlock(&mutex);
return NULL;
}
void* notifier(void* arg) {
pthread_mutex_lock(&mutex);
ready = true;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
return NULL;
}
join
-olni: memória és vezérlés kiszámíthatatlansága
pthread_mutex_lock()
-ot unlock()
-kal – akár kivételes útvonalon ispthread_cond_*
feltételes változókat a komplex várakozásra
Tulajdonság | pthread
|
std::thread (C++)
|
---|---|---|
Nyelv | C | C++11 és újabb |
Hordozhatóság | POSIX-only | Platformfüggetlen (elvben) |
API | Alacsony szintű | Magasabb absztrakció |
Könnyű használat | ❌ | ✅ |
Igen, a Cigarette Smokers Problem is remekül megvalósítható pthread_create
, pthread_mutex_t
, pthread_cond_t
használatával. A lényege, hogy:
A Pthreads egy erős, de alacsony szintű eszköztár a C/C++ programozóknak, ha párhuzamos, szál-alapú programozásban gondolkodnak. Előnye, hogy közvetlen hozzáférést ad a rendszer erőforrásaihoz és viselkedéséhez, de cserébe nagyobb felelősséget is ró a programozóra. Hibakezelés, szinkronizáció és adatversenyek megelőzése elengedhetetlen!