cpp_Thread_Mutex - 8BitsCoding/RobotMentor GitHub Wiki

cpp_Thread

cppreference

๊ธฐ์กด์— OS๋ณ„ ๋ณ„๋„๋กœ ๋Œ๋˜ thead๋ฅผ ํ•˜๋‚˜๋กœ ํ•ฉ์ณ๋ณด์ž!

๋‹จ, C++ํ‘œ์ค€์ด๊ธฐ์— ๋ชจ๋“  OS์—์„œ ๋Œ์•„๊ฐ€๊ฒŒ ๋งŒ๋“ค์—ˆ๋‹ค.

๊ทธ์— ๋”ฐ๋ฅธ ์“ฐ๊ธฐ ๋ถˆํŽธํ•œ ์ ์ด ๋ช‡ ๊ฐ€์ง€ ์กด์žฌํ•œ๋‹ค..


  • ๋‹ค๋ฅธ ์ฝ”์Šค์—์„œ ์“ฐ๋ ˆ๋”ฉ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ๋Œ€ํ•ด ๋ฐฐ์šด๋‹ค.
  • ๊ทธ๋ž˜์„œ C++์—์„œ ์“ฐ๋ ˆ๋”ฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ๋ฒ•์— ์ดˆ์ ์„ ๋งž์ถค
  • ํŠนํžˆ
    • ์“ฐ๋ ˆ๋“œ
    • ๋ฎคํ…์Šค
    • ์กฐ๊ฑด ๋ณ€์ˆ˜
    • ๋” ์žˆ์œผ๋‚˜, ์—ฌ๊ธฐ์„  ๋ฐฐ์šฐ์ง€ ์•Š๋Š”๋‹ค.

C++11 ์ด์ „์˜ ๋ฉ€ํ‹ฐ ์“ฐ๋ ˆ๋”ฉ

// Windwos
#include <Windows.h>

DWORD WINAPI PrintMessage()
{
    // ...
}

int main() {
    DWORD myThreadID;

    HANDLE myHandle = CreateThread(0, 0, PrintMessage, NULL, 0, &myThreadID);

    WaitForSingleObject(myHandle, INFINITE);
    // thread๊ฐ€ ์ข…๋ฃŒ๋ ๋•Œ ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.

    CloseHandle(myHandle);

    return 0;
}
// POSIX(pthread)
#include <pthread.h>

void *printMessage()
{
    // ...
}

int main() {
    pthread_t thread = 0;

    int result_code = pthread_create(&thread, NULL, printMessage, NULL);

    result_code = pthread_join(thread, NULL);

    return 0;
}

C++11 ์ด์ „์˜ ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋”ฉ

  • C++11 ์ „๊นŒ์ง€ ํ‘œ์ค€ ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋”ฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์—†์Œ
  • OS๋งˆ๋‹ค ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋”ฉ ๊ตฌํ˜„์ด ๋‹ฌ๋ž์Œ
    • ๋ฆฌ๋ˆ…์Šค/์œ ๋‹‰์Šค : POSIX(pthread)
    • ์œˆ๋„์šฐ ์“ฐ๋ ˆ๋“œ
    • ์œˆ๋„์šฐ์—์„œ pthread๋ฅผ ์‚ฌ์šฉํ• ์ˆœ ์žˆ์Œ(ver 1003.1๋งŒ)

์“ฐ๋ ˆ๋“œ ๊ฐœ์ฒด ๋งŒ๋“ค๊ธฐ (thread ์ƒ์„ฑ)

#include <iostream>
#include <string>
#include <thread>

void PrintMessage(const std::string& message)
{
    std::cout << message << std::endl;
}

int main() {
    std::thread thread(PrintMessage, "Message from a child thread");

    PrintMessage("Message from a main thread");

    return 0;
}

๋‹จ, ์œ„์˜ ์˜ˆ๋Š” Main์ด ๋๋‚˜๋„ Thread๊ฐ€ ๊ณ„์† ๋Œ์•„๊ฐ€๋Š” ์œ„ํ—˜์ด ์žˆ์Œ


ํ•ด๊ฒฐ๋ฒ•?

#include <iostream>
#include <string>
#include <thread>

void PrintMessage(const std::string& message)
{
    std::cout << message << std::endl;
}

int main() {
    std::thread thread(PrintMessage, "Message from a child thread");

    PrintMessage("Message from a main thread");

    thread.join();

    return 0;
}

์“ฐ๋ ˆ๋“œ ID ๊ตฌํ•˜๊ธฐ

#include <iostream>
#include <sstream>
#include <string>
#include <thread>

void PrintMessage(const std::string& message)
{
    std::cout << message << std::endl;
}

int main() {
    std::thread thread(PrintMessage, "Message from a child thread");

    std::thread::id childThreadOD = thread.get_id();
    std::stringstream ss;
    ss << childThreadID;
    std::string childThreadISStr = ss.str();
    
    PrintMessage("Waiting the child thread(ID : " + childThreadIDStr + ")");

    thread.join();

    return 0;
}

์“ฐ๋ ˆ๋“œ ๋–ผ์–ด ๋‚ด๊ธฐ

#include <iostream>
#include <string>
#include <thread>

void PrintMessage(const std::string& message)
{
    std::cout << message << std::endl;
}

int main() {
    std::thread thread(PrintMessage, "Message from a child thread");
    
    PrintMessage("Waiting the child thread");

    // ๋–ผ์–ด ๋‚ด๊ธฐ
    thread.detach();

    // ๋‹ค์‹œ ๋ถ™์ด๊ณ  ์‹ถ๋‹ค๋ฉด?
    if(thread.joinable())
    {
        thread.join();
    }

    return 0;
}

๋žŒ๋‹ค์™€ ์“ฐ๋ ˆ๋”ฉ

#include <iostream>
#include <string>
#include <thread>


int main() {
    auto PrintMessage = [](const std::string& message)
    {
        std::cout << message << std::endl;
    };

    std::thread thread(PrintMessage, "Message from a child thread");
    
    PrintMessage("Waiting the child thread");

    thread.join();

    return 0;
}

๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐ๋กœ ์ „๋‹ฌ

#include <iostream>
#include <string>
#include <thread>
#include <vector>

int main() {
    std::vector<int> list(100, 1);
    int result = 0;

    std::thread thread([](const std::vector<int>& v, int& result)
    {
        for( auto item : v )
        {
            result += item;
        }
    }, list, std::ref(result));

    thread.join();

    std::cout << "Result: " << result << std::endl;

    return 0;
}

๋„์šฐ๋ฏธ ํ•จ์ˆ˜๋“ค(this_thread)

  • ๋„ค์ž„์ŠคํŽ˜์ด์Šค ๊ทธ๋ฃน
  • ํ˜„์žฌ ์“ฐ๋ ˆ๋“œ์— ์ ์šฉ๋˜๋Š” ๋„์šฐ๋ฏธ ํ•จ์ˆ˜๋“ค์ด ์žˆ์Œ
    • get_id()
    • sleep_for()
    • sleep_until()
    • yield()
#include <iostream>
#include <chrono>
#include <string>
#include <thread>

void PrintCurrentTime() {/* ํ˜„์žฌ ์‹œ๊ฐ„ ์ถœ๋ ฅ */}

void PrintMessage(const std::string& message)
{
    std::cout << "Sleep now ... ";
    PrintCurrentTime();

    std::this_thread::sleep_for(std::chrono::seconds(3));
    // thread 3์ดˆ ์ž๋ผ

    std::cout << message << " ";
    PrintCurrentTime();
}

int main() {
    std::thread thread(PrintMessage, "Message from a child thread");
    
    PrintMessage("Waiting the child thread");

    thread.join();

    return 0;
}

๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ์—๊ฒŒ ์–‘๋ณดํ•˜๊ธฐ

auto end = std::chrono::high_resolution_clock::now() + delay;

while(std::chrono::high_resolution_clock_now() < end)
{
    std::this_thread::yield();
}

Mutex

๊ณต์œ  ์ž์› ์ž ๊ทธ๊ธฐ

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

void PrintMessage(const std::string& message)
{
    static std::mutex sMutex;
    // ๋ฌผ๋ก  ์ด๋Ÿฐ์‹์œผ๋กœ static์„ ์“ฐ๋Š”๊ฑด ์ข‹์ง€ ๋ชปํ•œ ์Šต๊ด€

    sMutex.lock();
    std::cout << message << std::endl;
    sMutex.unlock();
}

int main() {
    std::thread thread(PrintMessage, "Message from a child thread");
    
    PrintMessage("Waiting the child thread");

    thread.join();

    return 0;
}

๋ฎคํ…์Šค ํ”ํžˆ ํ•˜๋Š” ์‹ค์ˆ˜??

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

void PrintMessage(const std::string& message)
{
    static std::mutex sMutex;
    // ๋ฌผ๋ก  ์ด๋Ÿฐ์‹์œผ๋กœ static์„ ์“ฐ๋Š”๊ฑด ์ข‹์ง€ ๋ชปํ•œ ์Šต๊ด€

    sMutex.lock();
    std::cout << message << std::endl;
    // sMutex.unlock();
    // unlock์„ ์•ˆํ•œ๊ฒฝ์šฐ
}

int main() {
    std::thread thread(PrintMessage, "Message from a child thread");
    
    PrintMessage("Waiting the child thread");

    thread.join();

    return 0;
}

ํ•ด๊ฒฐ์ฑ… : std::scoped_lock(C++17)

๊ธฐ๋ณธ์ ์œผ๋กœ unlock์„ ์ž˜ํ•˜๋Š”๊ฒŒ ์ •๋‹ต์ด๊ณ ..

void PrintMessage(const std::string& message)
{
    static std::mutex sMutex;
    // ๋ฌผ๋ก  ์ด๋Ÿฐ์‹์œผ๋กœ static์„ ์“ฐ๋Š”๊ฑด ์ข‹์ง€ ๋ชปํ•œ ์Šต๊ด€

    std::scoped_lock<std::mutex> lock(sMutex);
    std::cout << message << std::endl;
}

std::scoped_lock(C++17) ์‚ฌ์šฉ๋ฒ• ์ถ”๊ฐ€

void PrintMessage(const std::string& message)
{
    static std::mutex sMutex;
    // ๋ฌผ๋ก  ์ด๋Ÿฐ์‹์œผ๋กœ static์„ ์“ฐ๋Š”๊ฑด ์ข‹์ง€ ๋ชปํ•œ ์Šต๊ด€

    // ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚˜๋ˆŒ ๊ฒฝ์šฐ scoped_lock์„ ๋ณ„๋„๋กœ ๊ฑธ ์ˆ˜ ์žˆ๋‹ค.
    {
        std::scoped_lock<std::mutex> lock(sMutex);
        std::cout << message << std::endl;    
    }

    {
        std::scoped_lock<std::mutex> lock(sMutex);
        std::cout << message << std::endl;    
    }
    
}

โš ๏ธ **GitHub.com Fallback** โš ๏ธ