같은 공간을 사용하기 때문에 생기는 문제점을 해결하는 방법을 알아보자.

#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include <mutex>

using namespace std;



int main()
{
	int shared_memory(0);
    auto count_func = [&](){
        for (int i=0;i<1000;++i)
        {
            this_thread::sleep_for(chrono::milliseconds(1));
            shared_memory++;
        }
    };
    
    thread t1 = thread(count_func);
    
    t1.join();
    
    cout << "After" << "\n";
    cout << shared_memory << "\n"; // 1000
    
    return 0;
}

#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include <mutex>

using namespace std;



int main()
{
	int shared_memory(0);
    auto count_func = [&](){
        for (int i=0;i<1000;++i)
        {
            this_thread::sleep_for(chrono::milliseconds(1));
            shared_memory++;
        }
    };
    
    thread t1 = thread(count_func);
 	thread t2 = thread(count_func);
    
    t1.join();
    t2.join();
    
    cout << "After" << "\n";
    cout << shared_memory << "\n"; // 2000이 나오지 않고 1962밖에 안나옴.
    // 병렬 처리 프로그래밍 할 때 어려운 점.
    // shared_memory를 갖고 와서 1을 더한 후에 결과값을 다시 덮어쓴다.
    // cpu로 읽어들인 사이에 thread2가 읽어서 더하는 경우에 문제가 생김.
    
    return 0;
}

#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include <mutex>

using namespace std;

mutex mtx;

int main()
{
	atomic<int> shared_memory(0);
    auto count_func = [&](){
        for (int i=0;i<1000;++i)
        {
            this_thread::sleep_for(chrono::milliseconds(1));
            
            // mtx.lock(); , mtx.unlock(); 으로도 처리 가능.
            shared_memory++; // int의 증감연산자가 아니라 atomic에 연산자 오버로딩이 되어있는 것.
            // shared_memory.fetch_add(1); // 이렇게도 사용 가능.
            // 그냥 int의 ++보단 느리다.
        }
    };
    
    thread t1 = thread(count_func);
 	thread t2 = thread(count_func);
    
    t1.join();
    t2.join();
    
    cout << "After" << "\n";
    cout << shared_memory << "\n"; // 2000이 나옴.
    
    return 0;
}

mutex lock_gurad

#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include <mutex>

using namespace std;

mutex mtx;

int main()
{
	int shared_memory(0);
    auto count_func = [&](){
        for (int i=0;i<1000;++i)
        {
            this_thread::sleep_for(chrono::milliseconds(1));
            
            // mtx.lock(); , mtx.unlock(); 으로도 처리 가능.
            std::lock_gurad lock(mtx); // 이렇게 쓰는 것을 권장.
            // std::scoped_lock lock(mtx); //조금 더 권장하는 방식. 이 scope를 벗어나는 순간 lock이 풀림.
            shared_memory++; 
            
            
        }
    };
    
    thread t1 = thread(count_func);
 	thread t2 = thread(count_func);
    
    t1.join();
    t2.join();
    
    cout << "After" << "\n";
    cout << shared_memory << "\n"; // 2000이 나옴.
    
    return 0;
}

#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include <mutex>

using namespace std;

int main()
{
	int shared_memory(0);
    auto count_func = [&](){
        for (int i=0;i<1000;++i)
        {
            //this_thread::sleep_for(chrono::milliseconds(1));
            shared_memory++;
        }
    };
    
    thread t1 = thread(count_func);
 	thread t2 = thread(count_func);
    
    t1.join();
    t2.join();
    
    cout << "After" << "\n";
    cout << shared_memory << "\n"; // millieseconds를 지우면 2000이 나옴.
    // 너무 빨리 처리해버려서 t1->t2 순으로 진행되기 때문에 문제가 생기지 않은 것처럼 보임.
    
    
    return 0;
}