multithreading

Üdvözlöm, Ön a multithreading szó jelentését keresi. A DICTIOUS-ban nem csak a multithreading szó összes szótári jelentését megtalálod, hanem megismerheted az etimológiáját, a jellemzőit és azt is, hogyan kell a multithreading szót egyes és többes számban mondani. Minden, amit a multithreading szóról tudni kell, itt található. A multithreading szó meghatározása segít abban, hogy pontosabban és helyesebben fogalmazz, amikor beszélsz vagy írsz. Amultithreading és más szavak definíciójának ismerete gazdagítja a szókincsedet, és több és jobb nyelvi forráshoz juttat.

Főnév

multithreading (tsz. multithreadings)

  1. (informatika) többszálú végrehajtás
  2. többszálú programozás

A multithreading (többszálú programozás) egy olyan programozási technika, amely lehetővé teszi, hogy egy program több végrehajtási szálon (thread) fusson párhuzamosan. A C++ szabványos könyvtára (STL) tartalmazza a std::thread osztályt, amely segít a szálkezelésben. Ebben a cikkben bemutatjuk a multithreading alapjait, a szinkronizálás módjait és néhány gyakori problémát.



1. Mi az a szál (thread)?

Egy szál egy olyan független végrehajtási egység, amely egy adott programon belül fut. Egy program futhat egyetlen szálon (single-threaded) vagy több szálon (multi-threaded).

Példa egy egyszálú programra:

#include <iostream>

void szamolas() {
    for (int i = 0; i < 5; i++) {
        std::cout << "Számolás: " << i << std::endl;
    }
}

int main() {
    szamolas();
    return 0;
}

Ebben az esetben a main() függvény egyetlen végrehajtási útvonalon fut.



2. Többszálú program létrehozása C++-ban

A C++11 bevezetésével az std::thread osztály lehetővé teszi több szál létrehozását és kezelését.

Példa két szál futtatására:

#include <iostream>
#include <thread>

void szamolas() {
    for (int i = 0; i < 5; i++) {
        std::cout << "Számolás: " << i << std::endl;
    }
}

int main() {
    std::thread szal(szamolas); // Létrehozunk egy új szálat
    szal.join(); // Megvárjuk, hogy a szál befejezze a munkáját
    std::cout << "Főprogram vége." << std::endl;
    return 0;
}

Ebben a programban: - std::thread szal(szamolas); → Létrehozunk egy új szálat, amely a szamolas függvényt hajtja végre. - szal.join(); → A főprogram vár, amíg a szál befejezi a futását.



3. Több szál egyidejű futtatása

Ha több szálat szeretnénk indítani, minden egyes szálhoz külön std::thread példányt hozunk létre.

Példa több szál indítására:

#include <iostream>
#include <thread>

void szamolas(int id) {
    for (int i = 0; i < 5; i++) {
        std::cout << "Szál " << id << ": " << i << std::endl;
    }
}

int main() {
    std::thread szal1(szamolas, 1);
    std::thread szal2(szamolas, 2);

    szal1.join();
    szal2.join();

    std::cout << "Főprogram vége." << std::endl;
    return 0;
}

Itt két különálló szál fut, és mindkettő párhuzamosan végrehajtja a szamolas függvényt.



4. Szinkronizáció és versenyhelyzetek

A párhuzamos végrehajtás versenyhelyzeteket (race condition) hozhat létre, ha több szál próbálja módosítani ugyanazt az erőforrást.

Versenyhelyzet példa

#include <iostream>
#include <thread>

int szamlalo = 0;

void novel() {
    for (int i = 0; i < 1000; i++) {
        szamlalo++; // Versenyhelyzet lehetősége
    }
}

int main() {
    std::thread szal1(novel);
    std::thread szal2(novel);

    szal1.join();
    szal2.join();

    std::cout << "Számláló értéke: " << szamlalo << std::endl; // Nem feltétlenül lesz 2000!
    return 0;
}

A fenti kód nem garantálja, hogy a számláló értéke 2000 lesz, mert a két szál egyszerre próbálja módosítani az értéket.



5. Mutex (kölcsönös kizárás)

A std::mutex segít megakadályozni a versenyhelyzeteket.

#include <iostream>
#include <thread>
#include <mutex>

int szamlalo = 0;
std::mutex mtx;

void novel() {
    for (int i = 0; i < 1000; i++) {
        mtx.lock();
        szamlalo++;
        mtx.unlock();
    }
}

int main() {
    std::thread szal1(novel);
    std::thread szal2(novel);

    szal1.join();
    szal2.join();

    std::cout << "Számláló értéke: " << szamlalo << std::endl;
    return 0;
}

Itt a mutex (mtx) biztosítja, hogy egyszerre csak egy szál férjen hozzá a szamlalo változóhoz.



6. Deadlock és megoldása

A deadlock egy olyan helyzet, amikor két vagy több szál vár egy erőforrásra, és egyik sem tud továbbhaladni.

Példa deadlockra:

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx1, mtx2;

void f1() {
    mtx1.lock();
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    mtx2.lock(); // Itt deadlock léphet fel
    std::cout << "f1 fut" << std::endl;
    mtx2.unlock();
    mtx1.unlock();
}

void f2() {
    mtx2.lock();
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    mtx1.lock(); // Itt deadlock léphet fel
    std::cout << "f2 fut" << std::endl;
    mtx1.unlock();
    mtx2.unlock();
}

int main() {
    std::thread t1(f1);
    std::thread t2(f2);

    t1.join();
    t2.join();
    return 0;
}

A fenti kód elakadhat, mert mindkét szál vár a másik által lezárt erőforrásra.

Megoldás: std::lock() függvény használata, amely egyszerre próbál több mutexet lezárni.



7. Condition Variables (Feltételes változók)

A std::condition_variable segít, ha egy szál várakozni szeretne egy eseményre.

Példa:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool kesz = false;

void dolgozo() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock,  { return kesz; });
    std::cout << "Munka elindult!" << std::endl;
}

void vezerlo() {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    {
        std::lock_guard<std::mutex> lock(mtx);
        kesz = true;
    }
    cv.notify_one();
}

int main() {
    std::thread t1(dolgozo);
    std::thread t2(vezerlo);

    t1.join();
    t2.join();

    return 0;
}

Itt a cv.wait() megvárja, amíg a vezerlo szál beállítja a kesz változót.



Összegzés

A multithreading nagy teljesítményt nyújt, de megfelelő szinkronizáció nélkül versenyhelyzetek és deadlockok alakulhatnak ki. A std::mutex, std::condition_variable és egyéb szinkronizációs eszközök segítenek a stabil kód megírásában.