C++11 并发编程

C++11 并发编程

参考书籍: https://chenxiaowei.gitbook.io/c-concurrency-in-action-second-edition-2019/

开启线程

#include <iostream>
#include <thread>  // 1
void hello()  // 2 
{
  std::cout << "Hello Concurrent World\n";
}
int main()
{
  std::thread t(hello);  // 3 创建线程并启动子线程
  t.join();  // 4 等待子线程完成
}
  • std::thread::hardware_concurrency()可以获取CPU核数

  • std::thread::id 线程id , std::this_thread::get_id() 获取当前线程id

共享数据竞争的问题

多个线程对同一个数据进行写(读)操作

解决办法

互斥量

std::mutexstd::lock_guard

std::list<int> g_vctNumbers;
std::mutex  g_mutex;

void Productor(int nValue)
{
	while (1)
	{
		//std::lock_guard<std::mutex>  guard(g_mutex);
		std::scoped_lock scopelock(g_mutex);
		g_vctNumbers.push_back(nValue);
	}
}

bool Consumer()
{
	bool bFlag = false;
	while (1)
	{
		//std::lock_guard<std::mutex>  guard(g_mutex);
		std::scoped_lock scopelock(g_mutex);
		if(g_vctNumbers.size() > 0)			
		g_vctNumbers.pop_back();
	}

	return  bFlag;
}
int main()
{
	std::vector<std::thread>  vctThds;

	//std::thread  t1( AddItem, 10);
	//std::thread t2(  FindItem, 10);
	//不能  先创建线程, 然后  push_back
	vctThds.emplace_back( Productor, 10 );
	vctThds.emplace_back( Consumer );

	for (auto &t : vctThds)
	{
		t.join();
	}
	std::cout << "hello world" << std::endl;
	system("pause");
    return 0;
}
死锁即解决方案
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>

using namespace std;

struct some_big_object
{
	std::string strName;
	std::string strAddr;
	int		nNo;
};

void swap(some_big_object& lhs, some_big_object& rhs)
{
	some_big_object tmp;
	tmp.nNo = lhs.nNo;
	tmp.strAddr = lhs.strAddr;
	tmp.strName = lhs.strName;
		
	lhs.nNo = rhs.nNo;
	lhs.strAddr = rhs.strAddr;
	lhs.strName = rhs.strName;

	rhs.nNo = tmp.nNo;
	rhs.strAddr = tmp.strAddr;
	rhs.strName = tmp.strName;

}

class X
{
//public:
private:
	some_big_object some_detail;
	std::mutex m;

public:
	X(some_big_object const& sd) :some_detail(sd) {}

#if 0
	friend void swap(X& lhs, X& rhs)
	{
		if (&lhs == &rhs)
			return;

		//传统方式: 手动管理
		std::cout << "starting lock two mutex" << std::endl;

		lhs.m.lock();
		rhs.m.lock();
		std::cout << "lock two mutex successed" << std::endl;

		swap(lhs.some_detail, rhs.some_detail);
		lhs.m.unlock();
		rhs.m.unlock();

		std::cout << "swaped successed." << std::endl;
	}
#elif 0

	friend void swap(X& lhs, X& rhs)
	{
		if (&lhs == &rhs)
			return;


		std::cout << "starting lock two mutex" << std::endl;

		std::lock(lhs.m, rhs.m); // 锁住两个互斥量

		std::cout << "lock two mutex successed" << std::endl;


		//将互斥量交由 std::lock_guard 来管理(释放锁)
		std::lock_guard<std::mutex> lock_a(lhs.m, std::adopt_lock); // 2
		std::lock_guard<std::mutex> lock_b(rhs.m, std::adopt_lock); // 3

		swap(lhs.some_detail, rhs.some_detail);

		std::cout << "swaped successed." << std::endl;
	}
#else 
	friend void swap(X& lhs, X& rhs)
	{
		if (&lhs == &rhs)
			return;

		std::cout << "starting lock two mutex" << std::endl;

		//在C++17中,  使用 scoped_lock 管理多个互斥量
		//构造即初始化(上锁)
		//析构时释放(解锁)
		std::scoped_lock   scopedlock(lhs.m, rhs.m);  //C++17

		swap(lhs.some_detail, rhs.some_detail);

		std::cout << "swaped successed." << std::endl;
	}

#endif


	friend std::ostream& operator << (std::ostream &outs, const X & x)
	{
		outs << "name:" << x.some_detail.strName << "; addr : "
			<< x.some_detail.strAddr << "; no:" << x.some_detail.nNo;
		return outs;
	}

}


int main()
{

	X a(some_big_object{"ZhangSan", "BeiJing", 9});
	X b(some_big_object{"LiSi", "NanJing", 100});

	//a.m.lock();

#if 0
	swap(a, b);
#else
	std::cout << "before swap: " << std::endl;
	std::cout << "a ---> " << a << std::endl;
	std::cout << "b ---> " << b << std::endl;
	
	
	auto func = [&a , &b]() {
		while (1)
		{
			swap(a, b);
		}
	};
	
	std::vector<std::thread> vctThds;

	for (int i = 0; i < std::thread::hardware_concurrency(); i++)
	{
		vctThds.emplace_back(  func  );
	}
	for (auto &thrd : vctThds)
	{
		thrd.join();
	}

#endif

	std::cout << "after swaped: " << std::endl;
	std::cout << "a ---> " << a << std::endl;
	
	std::cout << "b ---> " << b << std::endl;

	std::cout << "hello world" << std::endl;
	system("pause");
    return 0;
}

/**
*Date: 2020/02/02 18:04
*Author:yqq
*Descriptions:none
*/
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS  
#endif
#include <cstdio>
#include <iostream>
#include <atomic>

using namespace std;

int main(void)
{
	std::atomic_flag   atom_flag;// = ATOMIC_FLAG_INIT;
	if (!atom_flag.test_and_set(std::memory_order_acquire))
	{
		std::cout << "setted" << std::endl;
	}
	else
	{
		//if (atom_flag.test_and_set(std::memory_order_acquire)) //error
		atom_flag.clear();
		if (!atom_flag.test_and_set(std::memory_order_acquire))
		{
			std::cout << "setted" << std::endl;
		}
		std::cout << "not setted" << std::endl;
	}


	std::atomic<bool>  bFlag = false;
	bool bExpected = true;
	bFlag.compare_exchange_strong( bExpected, false); //如果bFlag当前的值与bExpected不同, 则将 

	std::cout << ((bFlag) ? ("true") : ("false") )<< std::endl;



	

	std::cout << "hello world" << std::endl;
	return 0;
}

/**
*Date: 2020/02/04 17:47
*Author:yqq
*Descriptions:none
*/
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS  
#endif
#include <cstdio>
#include <iostream>
#include <atomic>
#include <thread>

using namespace std;

int main(void)
{
	int a = 99;

	int* pa = &a ;


	std::atomic<int*> atomicPtr(pa);

	std::cout << * atomicPtr.load() << std::endl;

	int b = 55;
	atomicPtr.store(  &b );
	std::cout << * atomicPtr.load() << std::endl;

	if (atomicPtr.is_lock_free())
	{
		std::cout << "is lock_free" << std::endl;
	}
	else
	{
		std::cout << "is not lock free" << std::endl;
	}


	//atomicPtr.fetch_add();

	int nArr[100]{0};
	for (int i = 0; i < sizeof(nArr) / sizeof(nArr[0]); i++)
	{
		nArr[i] = i * 10;
	}

	std::atomic<int*> pArr( nArr );

	int* pTmp =  pArr.fetch_add(3);  // 先返回pArr  在 += 3
	std::cout << *pTmp << std::endl;  
	std::cout << *pArr.load() << std::endl;


	std::cout << "hello world" << std::endl;
	return 0;
}


/*


使用 std::call_once  和 std::once_flag 解决资源初始化多线程竞争问题

*/


#include <iostream>
#include <thread>
#include <mutex>
#include <string>
#include <chrono>
#include <vector>
#include <sstream>

using namespace std;


struct Printer
{
private:
    std::once_flag  __m_initFlag;

    void Init()
    {
        std::cout << "starting init printer" << std::endl;

        std::cout << "init finished." << std::endl;
    }

public:

    void Print( const std::string &strInput)
    {
        std::call_once( __m_initFlag, &Printer::Init, this );
        for(int i = 0; i < 10; i++)
        {
            std::ostringstream fmts;
            std::thread::id  tid = std::this_thread::get_id();
            
            fmts  << "thread " << std::this_thread::get_id() << "'s i is " << i << strInput;
            std::this_thread::sleep_for(  std::chrono::microseconds(50) );
            std::cout <<  fmts.str() << std::endl;
        }
    }

};



#if 0
int main()
{
    Printer  p;
    // p.Print("hello");


    std::vector<std::thread>  vctThds;

    for(int i = 0; i < 4; i++)
    {
        //std::thread  t1( &Printer::Print,  &p, "thread2" );
        vctThds.emplace_back( &Printer::Print, &p, "");

    }

    for(auto &t : vctThds)
    {
        if(t.joinable())
            t.join();
    }


    /*
    std::thread  t2( &Printer::Print,  &p, "thread3" );
    if(t1.joinable())
        t1.join();
    if(t2.joinable())
        t2.join();
    */

    
    return 0;
}
#endif

#include <iostream>
#include <list>
#include <random>
#include <algorithm>
#include <future>
#include <thread>
#include <chrono>

template<typename T>
std::list<T> parallel_quick_sort(std::list<T> input)
{
  if(input.empty())
  {
    return input;
  }
  std::list<T> result;
  result.splice(result.begin(),input,input.begin());
  T const& pivot=*result.begin();

  auto divide_point=std::partition(input.begin(),input.end(),
                [&](T const& t){return t<pivot;});

  std::list<T> lower_part;
  lower_part.splice(lower_part.end(),input,input.begin(),
                divide_point);

  std::future<std::list<T> > new_lower(  // 1
                std::async(&parallel_quick_sort<T>,std::move(lower_part)));

  auto new_higher(
                parallel_quick_sort(std::move(input)));  // 2

  result.splice(result.end(),new_higher);  // 3
  result.splice(result.begin(),new_lower.get());  // 4
  return result;
}


#if 0
int main()
{
    //std::default_random_engine generator;
    std::mt19937  generator;
    //std::random_device generator;  //不确定的随机数生成器
    std::uniform_int_distribution<int> distribution(-10000, 10000);

    std::list<int> lstNumbers;
    for(int i = 0; i < 1000; i++)
    {
        lstNumbers.emplace_back( distribution(generator) );
    }

    auto startTime = std::chrono::high_resolution_clock::now();
    auto lstSorted = parallel_quick_sort<int>(lstNumbers);
    auto endTime  = std::chrono::high_resolution_clock::now();

    std::cout << "elasped time: " << (endTime - startTime).count() << std::endl;
    //std::cout <<  std::chrono::duration_cast<std::chrono::seconds>((endTime - startTime).count())  << std::endl;
    

    for(auto &item : lstSorted)
    {
        std::cout << item << "\t";
    }
    std::cout << std::endl;
    
    return 0;
}
#endif


#include <iostream>
#include <thread>
#include <queue>
#include <memory>
#include <mutex>
#include <condition_variable>
#include <string>
#include <sstream>
#include <chrono>
#include <atomic>

using namespace std;

template<typename T>
class threadsafe_queue
{
private:
  mutable std::mutex mut;  // 1 互斥量必须是可变的 
  std::queue<T> data_queue;
  std::condition_variable data_cond;
public:
  threadsafe_queue()
  {}
  threadsafe_queue(threadsafe_queue const& other)
  {
    std::lock_guard<std::mutex> lk(other.mut);
    data_queue=other.data_queue;
  }

  void push(T new_value)
  {
    std::lock_guard<std::mutex> lk(mut);
    data_queue.push(new_value);
    data_cond.notify_one();
  }

    /**
     * wait()会去检查这些条件(通过调用所提供的lambda函数),
     * 当条件满足(lambda函数返回true)时返回。如果条件不满足(lambda函数返回false),
     * wait()函数将解锁互斥量,并且将这个线程(上段提到的处理数据的线程)置于阻塞或等待状态。
     * 当准备数据的线程调用notify_one()通知条件变量时,处理数据的线程从睡眠状态中苏醒,
     * 重新获取互斥锁,并且再次检查条件是否满足。在条件满足的情况下,从wait()返回并继续持有锁;
     * 当条件不满足时,线程将对互斥量解锁,并且重新开始等待。这就是为什么用std::unique_lock而
     * 不使用std::lock_guard——等待中的线程必须在等待期间解锁互斥量,并在这之后对互斥量再次上锁,
     * 而std::lock_guard没有这么灵活。如果互斥量在线程休眠期间保持锁住状态,
     * 准备数据的线程将无法锁住互斥量,也无法添加数据到队列中;同样的,等待线程也永远不会知道条件何时满足。
     */
    void wait_and_pop(T& value)
    {
        std::unique_lock<std::mutex> lk(mut);
        data_cond.wait(lk,[this]{return !data_queue.empty();});
        value=data_queue.front();
        data_queue.pop();
    }

  std::shared_ptr<T> wait_and_pop()
  {
    std::unique_lock<std::mutex> lk(mut);
    data_cond.wait(lk,[this]{return !data_queue.empty();});
    std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));
    data_queue.pop();
    return res;
  }

  bool try_pop(T& value)
  {
    std::lock_guard<std::mutex> lk(mut);
    if(data_queue.empty())
      return false;
    value=data_queue.front();
    data_queue.pop();
    return true;
  }

  std::shared_ptr<T> try_pop()
  {
    std::lock_guard<std::mutex> lk(mut);
    if(data_queue.empty())
      return std::shared_ptr<T>();
    std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));
    data_queue.pop();
    return res;
  }

  bool empty() const
  {
    std::lock_guard<std::mutex> lk(mut);
    return data_queue.empty();
  }
};





#if 0
int main()
{
    threadsafe_queue<std::string>   q;
    // std::condition_variable condvarFinished;
    //std::atomic_flag  finishedFlag(false);
    std::atomic_bool   finishedFlag = false;

    std::thread   t1([&](){

        for(int i = 0; i < 1000; i++){
            std::ostringstream  fmts;
            fmts << "this is " << i;

            std::this_thread::sleep_for( std::chrono::microseconds( 10 ) );
            std::cout << "push " << i << std::endl;
            q.push(fmts.str());
        }

        finishedFlag = true;

        std::cout << "productor finished..." << std::endl;

    });


    std::thread t2([&](){

        while(!finishedFlag){
            std::string strTmp = "";
            q.wait_and_pop(strTmp);
            std::cout << "got :" << strTmp << std::endl;
        }

        std::cout << "consumer finished..." << std::endl;

    });

    if(t1.joinable())
        t1.join();
    
    if(t2.joinable())
        t2.join();

    return 0;
}
#endif


// CPP11Concurency.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <thread>
#include <chrono>


void thread_proc()
{
	for (int i = 0; i < 10; i++)
	{
		std::cout << "thread :" << std::this_thread::get_id() << std::endl;
		std::this_thread::sleep_for( std::chrono::microseconds(10) );
	}

}


struct Functor
{
	char* m_pEchoStr = nullptr;
	
	void operator()()
	{
		for (int i = 0; i < 10; i++)
		{
			sprintf(m_pEchoStr, "ehco : %d", i);
			std::cout << "Functor :" << std::this_thread::get_id() << "   echo str:" << m_pEchoStr << std::endl;
			std::this_thread::sleep_for(std::chrono::microseconds(10));
		}

	}
};



int main()
{

	//1.通过普通函数, 作为thread的构造函数参数, 创建线程

	std::thread  t1(thread_proc); //创建并立即启动线程
	//t1.join();
	t1.detach();
	
	if (!t1.joinable())  //如果线程已经detach, 则joinable为false 
	{
		std::cout << "can't join thread  " << t1.get_id() << std::endl;
	}



	//2.使用仿函数(函数对象) 作为thread构造函数参数, 创建线程
	//int n = 999999999;
	//std::string  strTmp("hello world");
	//functor.m_pEchoStr = strTmp.c_str();

	char szBuf[1024] = "hello world";
	Functor functor;
	functor.m_pEchoStr = szBuf;
	std::thread  t2(functor);
	t2.join();
	//t2.detach();   //!!!!特别注意:  detach 需要注意  线程参数的生命周期, 否则会发生不可预料的错误



	//3.使用lambda函数作为thread构造函数的参数, 创建线程
	std::thread  t3([&]() {
		for (int i = 0; i < 5; i++)
		{
			sprintf(szBuf, "this is lamdba %d", i);
			std::cout << "lambda : " << i << " ------>" << szBuf << std::endl;;
		}
	});
	t3.join();




    std::cout << "Hello World!\n";
}


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

std::condition_variable cv;
bool done = false;
std::mutex m;


void worker()
{
    for(int i = 0; i < 10; i++)
    {
        std::this_thread::sleep_for( std::chrono::milliseconds(300) );
        cv.notify_all(); //通知所有
        //cv.notify_one();
    }
    done  = true;
}


bool wait_loop()
{
  auto const timeout= std::chrono::steady_clock::now()+
      std::chrono::milliseconds(500);
  std::unique_lock<std::mutex> lk(m);
  while(!done)
  {
    std::cv_status   cvStatus  = cv.wait_until( lk, timeout );
    if(std::cv_status::timeout == cvStatus)
    {
        std::cout <<  std::this_thread::get_id()  << " timeout" << std::endl;
        break;
    }
    else if(std::cv_status::no_timeout == cvStatus)
    {
        std::cout << "waited condition_variable" << std::endl;
        break;
    }
    else{}

  }
  return done;
}

#if 0
int main()
{
    //wait_loop();
    std::thread t1(  wait_loop );
    std::thread t11(  wait_loop );
    std::thread t111(  wait_loop );
    std::thread  t2( worker );

    t1.join();
    t11.join();
    t111.join();
    t2.join();

    return 0;
}
#endif

#include <functional>
#include <iostream>
#include <string>
#include <map>


int add(int a, int b)
{
    return a + b;
}

int mul(int a, int b)
{
    return a * b;
}



#if 0
int main()
{

    auto fn = std::function<int(int, int)>(add);
    std::map<std::string,  decltype(fn) >  mapFns;

    mapFns.insert( std::make_pair( "+", fn ));
    mapFns.insert( std::make_pair("*", std::function (mul)) );

    mapFns.insert( std::make_pair("-", [](int a, int b) -> int{
        return a - b;
    }) );


    std::cout <<   mapFns["*"](6, 9) << std::endl;  //54
    std::cout <<   mapFns["+"](6, 9) << std::endl;  //15
    std::cout <<   mapFns["-"](6, 9) << std::endl;  //-3

    return 0;
}
#endif

#include <iostream>
#include <future>
#include <thread>
#include <string>
#include <memory>
#include <chrono>
#include <cmath>


using namespace std;


double square_root(double x)
{
  if(x<0)
  {
    throw std::out_of_range("x<0");
  }
  return sqrt(x);
}

#if 0
int main()
{
    /**
     *  launch::async表示开启一个新的线程执行fn
        launch::deferred 表示fn推迟到future::wait/get时才执行
        launch::async|launch::deferred表示由库自动选择哪种机制执行fn,和第一种构造方式async(fn,args)策略相同
     */
    std::future<double> f=std::async(square_root, 9);

    std::cout << "doing other things..." << std::endl;

    for(int i = 0; i < 1000; i++)
    {
        std::cout << "other thing" << std::endl;
    }


    double y = f.get();

    std::cout << "reuslt = "  << y << std::endl;


    return 0;
}
#endif



/**
 * packaged_task 和 std::function 很像
 * 
 */


// packaged_task example
#include <iostream>     // std::cout
#include <future>       // std::packaged_task, std::future
#include <chrono>       // std::chrono::seconds
#include <thread>       // std::thread, std::this_thread::sleep_for

// count down taking a second for each value:
int countdown (int from, int to) 
{
  for (int i=from; i!=to; --i) {
    std::cout << i << '\n';
    std::this_thread::sleep_for(std::chrono::seconds(1));
  }
  std::cout << "Lift off!\n";
  return from-to;
}

#if 0
int main ()
{
  std::packaged_task<int(int,int)> tsk (countdown);   // set up packaged_task
  std::future<int> ret = tsk.get_future();            // get future

  std::thread th (std::move(tsk),10,0);   // spawn thread to count down from 10 to 0

  // ...

  int value = ret.get();                  // wait for the task to finish and get result

  std::cout << "The countdown lasted for " << value << " seconds.\n";

  th.join();

  return 0;

}
#endif


/*
#include <iostream>       // std::cout
#include <functional>     // std::ref
#include <thread>         // std::thread
#include <future>         // std::promise, std::future

void print_int(std::future<int>& fut) 
{
    int x = fut.get(); // 获取共享状态的值.
    std::cout << "value: " << x << '\n'; // 打印 value: 10.
}

int main ()
{
    std::promise<int> prom; // 生成一个 std::promise<int> 对象.
    std::future<int> fut = prom.get_future(); // 和 future 关联.
    std::thread t(print_int, std::ref(fut)); // 将 future 交给另外一个线程t.
    prom.set_value(10); // 设置共享状态的值, 此处和线程t保持同步.
    t.join();
    return 0;
}
*/

/*
#include <iostream>       // std::cin, std::cout, std::ios
#include <functional>     // std::ref
#include <thread>         // std::thread
#include <future>         // std::promise, std::future
#include <exception>      // std::exception, std::current_exception

void get_int(std::promise<int>& prom) 
{
    int x;
    std::cout << "Please, enter an integer value: ";
    std::cin.exceptions (std::ios::failbit);   // throw on failbit
    try
    {
        std::cin >> x;                         // sets failbit if input is not int
        prom.set_value(x);
    } 
    catch (std::exception&) 
    {
        prom.set_exception(std::current_exception());
    }
}

void print_int(std::future<int>& fut) 
{
    try {
        int x = fut.get();
        std::cout << "value: " << x << '\n';
    } catch (std::exception& e) {
        std::cout << "[exception caught: " << e.what() << "]\n";
    }
}

int main ()
{
    std::promise<int> prom;
    std::future<int> fut = prom.get_future();

    std::thread th1(get_int, std::ref(prom));
    std::thread th2(print_int, std::ref(fut));

    th1.join();
    th2.join();
    return 0;
}
*/

#include <iostream>       // std::cin, std::cout, std::ios
#include <functional>     // std::ref
#include <thread>         // std::thread
#include <future>         // std::promise, std::future
#include <exception>      // std::exception, std::current_exception




/*
int main()
{

    std::thread  t1();



    return 0;
}
*/




#include <iostream>
#include <list>
#include <random>
#include <algorithm>
#include <thread>
#include <chrono>


template<typename T>
std::list<T> sequential_quick_sort(std::list<T> input)
{
  if(input.empty())
  {
    return input;
  }
  std::list<T> result;
  result.splice(result.begin(),input,input.begin());  // 1
  T const& pivot=*result.begin();  // 2

  auto divide_point=std::partition(input.begin(),input.end(),
             [&](T const& t){return t<pivot;});  // 3

  std::list<T> lower_part;
  lower_part.splice(lower_part.end(),input,input.begin(), divide_point);  // 4
  auto new_lower( sequential_quick_sort(std::move(lower_part)));  // 5
  auto new_higher(sequential_quick_sort(std::move(input)));  // 6

  result.splice(result.end(),new_higher);  // 7
  result.splice(result.begin(),new_lower);  // 8
  return result;
}

#if 0
int main()
{
    //std::default_random_engine generator;
    std::mt19937  generator;
    //std::random_device generator;  //不确定的随机数生成器
    std::uniform_int_distribution<int> distribution(-10000, 10000);

    std::list<int> lstNumbers;
    for(int i = 0; i < 1000; i++)
    {
        lstNumbers.emplace_back( distribution(generator) );
    }

    auto startTime = std::chrono::high_resolution_clock::now();
    auto lstSorted = sequential_quick_sort<int>(lstNumbers);
    auto endTime  = std::chrono::high_resolution_clock::now();

    std::cout << "elasped time: " << (endTime - startTime).count() << std::endl;
    //std::cout << std::chrono::duration<double, std::chrono::seconds> (endTime - startTime).count()  << std::endl;

    for(auto &item : lstSorted)
    {
        std::cout << item << "\t";
    }
    std::cout << std::endl;
    
    return 0;
}
#endif

/**
*Date: 2020/02/04 19:01
*Author:yqq
*Descriptions:
	
	1.多个线程可以读写不同shared_ptr(副本)(即使shared_ptr指向同一个对象)
	2.多个线程可以读取同一个 shared_ptr
	3.多个线程不能写同一个shared_ptr , 除非使用 原子函数, 如:  std::atomic_load  std::atomic_store


*/
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS  
#endif
#include <cstdio>
#include <iostream>
#include <atomic>
#include <thread>
#include <memory>
#include <chrono>
#include <vector>

using namespace std;

struct  Printer
{
	int m_nA = 0;

	Printer(int a) : m_nA(a)
	{
	}

	void Show()
	{
		//std::this_thread::sleep_for( std::chrono::microseconds(100) );
		std::cout << "thread " << std::this_thread::get_id() << " m_nA: " << m_nA << std::endl;
		std::cout << this << std::endl;
		this->m_nA = 99;
	}
};


std::shared_ptr<Printer>  g_Data;

void ProcessGlobalData()
{
	while (nullptr == g_Data);

	//for (int i = 0; i < 10; i++)
	while(1)
	{
		//shared_ptr<Printer> spData = std::atomic_load( &g_Data);
		shared_ptr<Printer> spData = g_Data;
		spData->Show();
	}
}

#if 0
void UpdateGlobalData()
{
	for (int i = 0; i < 10; i++)
	{
		std::this_thread::sleep_for( std::chrono::microseconds(1) );
		std::shared_ptr<Printer> spTmp = std::make_shared<Printer>( i );
		std::atomic_store( &g_Data, spTmp );
	}
}
#endif

#if 0

//多个线程读取同一个  shared_ptr
void UpdateGlobalData()
{
	std::shared_ptr<Printer> spTmp = std::make_shared<Printer>(9999);
	g_Data = spTmp;
	for (int i = 0; ; )
	{
		std::this_thread::sleep_for(std::chrono::microseconds(1));
		spTmp->m_nA = i;
	}
}
#endif

//多个线程写同一个  shared_ptr
void UpdateGlobalData()
{
	//std::shared_ptr<Printer> spTmp = std::make_shared<Printer>(9999);
	for (int i = 0; ; )
	{
		//g_Data = spTmp;
		if (nullptr == g_Data)
		{
			std::shared_ptr<Printer> spTmp = 
			g_Data = std::make_shared<Printer>(9999);
		}

		std::cout << "hello" << std::endl;
		g_Data->Show();
	}
}


//多个线程写同一个  shared_ptr
void UpdateGlobalDataToNullptr()
{
	for (int i = 0; ; )
	{
		g_Data = nullptr;
	}
}



int main(void)
{
	std::vector<std::thread>  vctThreads;

#if 0
	vctThreads.emplace_back( UpdateGlobalData );

	//多个线程读取同一个  shared_ptr
	vctThreads.emplace_back( ProcessGlobalData );
	vctThreads.emplace_back( ProcessGlobalData );
	vctThreads.emplace_back( ProcessGlobalData );
	vctThreads.emplace_back( ProcessGlobalData );
#endif


	vctThreads.emplace_back( UpdateGlobalData );
	vctThreads.emplace_back( UpdateGlobalData );
	vctThreads.emplace_back( UpdateGlobalData );
	vctThreads.emplace_back( UpdateGlobalData );
	vctThreads.emplace_back( UpdateGlobalDataToNullptr );
	
	for (auto& thd : vctThreads)
	{
		thd.join();
	}

	std::cout << "hello world" << std::endl;
	return 0;
}


/**
 * 2020-01-31
 * 
 * 如果只有一个全局变量 , 直接使用 static就可以解决初始化竞争的问题,  
 * 
 * 注意: 仅仅是解决 "初始化竞争",  而不能解决初始化后的 "资源竞争"
 * 
 * 
 */


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


class MySingleton
{
protected:

    MySingleton(){}
    ~MySingleton() {}

public:

    void Print()
    {
        std::cout << this << std::endl;
        std::cout << "this is singleton pattern" << std::endl;
    }

    /*virtual void ~Print()
    {
        std::cout << "~Print()" << std::endl;
    }*/

    static MySingleton * GetInstance()
    {
        /*
        static MySingleton *pInstance = nullptr;
        if(nullptr == pInstance)
        {
            pInstance = new MySingleton();  
        }
        return pInstance;
        */


        //参考:  https://chenxiaowei.gitbook.io/c-concurrency-in-action-second-edition-2019/3.0-chinese/3.3-chinese
        //在C++11后, 此过程是线程安全的. 所以不必再使用互斥量
        static MySingleton *pInstance = new MySingleton(); 
        return pInstance;
        
    }

};




#if 0
int main()
{
    std::cout << "new debug" << std::endl;
    MySingleton *pInst = MySingleton::GetInstance();
    MySingleton *pInst2 = MySingleton::GetInstance();
    pInst->Print();
    pInst2->Print();

    return 0;
}
#endif


/**
 *  模板偏特化
 */

#include <iostream>

using namespace std;

template<typename T1,typename T2>
class Test
{
public:
    Test(T1 i,T2 j):a(i),b(j){cout<<"模板类"<<endl;}
private:
    T1 a;
    T2 b;
};

//必须有  上面泛化  才能有下面的 偏特化
template<typename T1,typename T2> //这是范围上的偏特化
class Test<T1*,T2*>
{
public:
    Test(T1* i,T2* j):a(i),b(j){cout<<"指针偏特化"<<endl;}
private:
    T1* a;
    T2* b;
};

/*
int main()
{

    return 0;
}
*/

// splicing lists
#include <iostream>
#include <list>

#if 0
int main ()
{
  std::list<int> mylist1, mylist2;
  std::list<int>::iterator it;

  // set some initial values:
  for (int i=1; i<=4; ++i)
     mylist1.push_back(i);      // mylist1: 1 2 3 4

  for (int i=1; i<=3; ++i)
     mylist2.push_back(i*10);   // mylist2: 10 20 30

  it = mylist1.begin();
  ++it;                         // points to 2

  mylist1.splice (it, mylist2); // mylist1: 1 10 20 30 2 3 4
                                // mylist2 (empty)
                                // "it" still points to 2 (the 5th element)
                                          
  mylist2.splice (mylist2.begin(),mylist1, it);
                                // mylist1: 1 10 20 30 3 4
                                // mylist2: 2
                                // "it" is now invalid.
  it = mylist1.begin();
  std::advance(it,3);           // "it" points now to 30

  mylist1.splice ( mylist1.begin(), mylist1, it, mylist1.end());
                                // mylist1: 30 3 4 1 10 20

    std::cout <<  "now *it = " << *it << std::endl;

  std::cout << "mylist1 contains:";
  for (it=mylist1.begin(); it!=mylist1.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  std::cout << "mylist2 contains:";
  for (it=mylist2.begin(); it!=mylist2.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}
#endif

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

using namespace std;

struct some_big_object
{
	std::string strName;
	std::string strAddr;
	int		nNo;
};

void swap(some_big_object& lhs, some_big_object& rhs)
{
	some_big_object tmp;
	tmp.nNo = lhs.nNo;
	tmp.strAddr = lhs.strAddr;
	tmp.strName = lhs.strName;
		
	lhs.nNo = rhs.nNo;
	lhs.strAddr = rhs.strAddr;
	lhs.strName = rhs.strName;

	rhs.nNo = tmp.nNo;
	rhs.strAddr = tmp.strAddr;
	rhs.strName = tmp.strName;

}

class X
{

private:
	some_big_object some_detail;
	std::mutex m;

public:
	X(some_big_object const& sd) :some_detail(sd) {}

#if 0
	friend void swap(X& lhs, X& rhs)
	{
		if (&lhs == &rhs)
			return;

		//传统方式: 手动管理
		std::cout << "starting lock two mutex" << std::endl;

		lhs.m.lock();
		rhs.m.lock();
		std::cout << "lock two mutex successed" << std::endl;

		swap(lhs.some_detail, rhs.some_detail);
		lhs.m.unlock();
		rhs.m.unlock();

		std::cout << "swaped successed." << std::endl;
	}
#elif 0

	friend void swap(X& lhs, X& rhs)
	{
		if (&lhs == &rhs)
			return;


		std::cout << "starting lock two mutex" << std::endl;

		std::lock(lhs.m, rhs.m); // 锁住两个互斥量

		std::cout << "lock two mutex successed" << std::endl;


		//将互斥量交由 std::lock_guard 来管理(释放锁)
		std::lock_guard<std::mutex> lock_a(lhs.m, std::adopt_lock); // 2
		std::lock_guard<std::mutex> lock_b(rhs.m, std::adopt_lock); // 3

		swap(lhs.some_detail, rhs.some_detail);

		std::cout << "swaped successed." << std::endl;
	}
#elif  0
	friend void swap(X& lhs, X& rhs)
	{
		if (&lhs == &rhs)
			return;

		std::cout << "starting lock two mutex" << std::endl;

		//在C++17中,  使用 scoped_lock 管理多个互斥量
		//构造即初始化(上锁)
		//析构时释放(解锁)
		std::scoped_lock   scopedlock(lhs.m, rhs.m);  //C++17

		swap(lhs.some_detail, rhs.some_detail);

		std::cout << "swaped successed." << std::endl;
	}

#else 
	friend void swap(X& lhs, X& rhs)
	{
		if (&lhs == &rhs)
			return;

		std::cout << "starting lock two mutex" << std::endl;


		//
		std::unique_lock<std::mutex> lock_a( lhs.m, std::defer_lock );
		std::unique_lock<std::mutex> lock_b( rhs.m, std::defer_lock );

		std::lock( lock_a, lock_b );


		swap(lhs.some_detail, rhs.some_detail);

		std::cout << "swaped successed." << std::endl;
	}

#endif


	friend std::ostream& operator << (std::ostream &outs, const X & x)
	{
		outs << "name:" << x.some_detail.strName << "; addr : "
			<< x.some_detail.strAddr << "; no:" << x.some_detail.nNo;
		return outs;
	}

};

#if 0

int main()
{

	X a(some_big_object{"ZhangSan", "BeiJing", 9});
	X b(some_big_object{"LiSi", "NanJing", 100});

	//a.m.lock();

#if 0
	swap(a, b);
#else
	std::cout << "before swap: " << std::endl;
	std::cout << "a ---> " << a << std::endl;
	std::cout << "b ---> " << b << std::endl;
	
	
	auto func = [&a , &b]() {
		//while (1)
		for(int i = 0; i < 10000; i++)
		{
			std::this_thread::sleep_for( std::chrono::microseconds(10) );
			swap(a, b);
		}
	};
	
	std::vector<std::thread> vctThds;

	for (int i = 0; i < std::thread::hardware_concurrency(); i++)
	{
		vctThds.emplace_back(  func  );
	}
	for (auto &thrd : vctThds)
	{
		thrd.join();
	}

#endif

	std::cout << "after swaped: " << std::endl;
	std::cout << "a ---> " << a << std::endl;
	
	std::cout << "b ---> " << b << std::endl;

	std::cout << "hello world" << std::endl;
	system("pause");
    return 0;
}
#endif

/**
*Date: 2020/01/11 15:28
*Author:yqq
*Descriptions:   c++11   thread ����
*/
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS  
#endif
#include <cstdio>
#include <iostream>
#include <thread>
#include <string>


using namespace std;



void MyPrintThreadProc(int n, const char *pszTmp)
{
	std::cout << "n" << n << "str: " << pszTmp;
}


int main(void)
{
	const char *pszTmp  = "hwllo";
	int n = 999;
	std::thread t1(MyPrintThreadProc, n, pszTmp);

	t1.join();
	

	std::cout << "hello world" << std::endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值