C++11同時とマルチスレッドまとめ(二)--排他的反発ロック--mutex,lock_guardyと他のmutex


文書ディレクトリ


(一)スレッド概念、作成およびパラメータ伝達(二)排他的反発ロック–mutex,lock_guardyと他のmutex(3)unique_lock置換lock_guardy(四)単一例モード(Singleton)でのスレッドセキュリティ問題(五)window臨界領域(六)condition_variable条件変数(7)std::async非同期タスクとstd::future<>(8)packaged_task<>とpromise<>(九)原子操作atomic<>の概要
(1)ロックの導入とデッドロック
  • は、複数のスレッドが作成されると、各スレッド間で順次不定に実行されるため、システムによってスケジューリングされる.
  • 共有データについては、複数のスレッドが同時にメモリ操作を行うことで異常が発生する
  • .
  • 共有データを操作する場合、共有データを保護するために、共有データをロックする必要がある.
  • は、2つ以上の反発ロックがデッドロック問題を生じる可能性があることに注意する.すなわち、2つのロックは互いに相手の解放を待つ、プログラムロックは
  • 動かない.
    (2)mutexとlock_guard
    1.listは順次アクセス効率が高い、vector無秩序効率が高い.複数のスレッドが共有データを同時に読み書きすると必ずエラーが発生し、システムが不安定になる.std::mutexオブジェクトlock()unlock()はペアでなければならない.そうしないとデッドロック4.std::lock_guard()クラステンプレートは自動的にロックを解除し、lock()unlock()を使用して作用ドメインから解析解5を離れることはできない.デッドロック、少なくとも2つの反発量があり、反発量の間で互いに待機する.一般的なソリューションlockの順序は一致する.std::lock(1,2)同時ロックまたは非同時ロック9を使用する.std::lock()とstd::lock_guard()ブレンド使用転送std::adopt_lock()すなわちクラス内部でlockを呼び出さない
  • mutex使用方法
  • 	std::mutex m_mutex;
    	m_mutex.lock()
    	//...
    	// 
    	//...
    	m_mutex.unlock()
    
  • lock_guardは,プロジェクトが大きすぎると反発量が多すぎるとロック解除を忘れ,プログラムの問題を引き起こす可能性があるためlock_の導入を容易にするために使用する.guard自動ロック解除
  • 	std::mutex m_mutex;
    	std::lock_guard<mutex> lockguard(m_mutex); // 
    	//...
    	// , 
    	//...
    
  • lock_guard第2パラメータ
  • 	std::mutex m_mutex;
    	m_mutex.lock();  // 
    	std::lock_guard<mutex> lockguard(m_mutex, std::adopt_lock); // 
    	//...
    	// , 
    	//...
    
  • コードセグメント1
  • を参照
    (3)recursive_mutexとtimed_mutex
  • 複数のスレッド間で共有リソースを操作するにはロックが必要ですが、ロックが必要な関数またはスレッドが呼び出されている可能性があります.ロック_を使用すると、ロックが繰り返される可能性があります.guardは繰り返しロックによってクラッシュするため、再帰ロック
  • が導入される.
    (1)recursive_mutex再帰排他反発量1.複数回lock 2.効率が低く、小さいサイズが大きい3.再帰回数が限られ、超えると異常が発生する.乱用するのではなく、コード空間最適化(2)std::timed_を考慮するmutex帯域タイムアウトの排他反発量1.時間帯std::chrono::milliseconds time(1000);//1000ミリ秒2を定義.try_lock_for(time)はブール値の着信待ち時間を返し、待ち時間を超えるとロックが取れず、渋滞を解除して実行を継続する.try_lock_until(chrono::steady_clock::now()+time)はブール値を返し、将来の時点に転送し、上(3)recursive_timed_mutex用法類推
    -コードセグメント1
    #include 
    #include
    #include
    #include
    
    using namespace std;
    
    
    class CReadAndWrite
    {
    public:
    	CReadAndWrite() {};
    	void read();
    	void wirte();
    
    private:
    	list<int> m_list;
    	mutex m_mutex1;
    	mutex m_mutex2;
    };
    
    void CReadAndWrite::wirte()
    {
    	for (int i = 0; i < 1000; i++)
    	{
    		//std::lock(m_mutex1, m_mutex2);  // ,  adopt_lock
    
    		//std::lock_guard l1(m_mutex1,std::adopt_lock);  
    		//std::lock_guard l2(m_mutex2, std::adopt_lock);
    
    		std::lock_guard<mutex> l1(m_mutex1);  // 
    		std::lock_guard<mutex> l2(m_mutex2);
    		m_list.push_back(i);
    		cout << "wirite  " << i << endl;
    	}
    }
    
    void CReadAndWrite::read()
    {
    	for (int i = 0; i < 10000; i++)
    	{
    		if (m_list.size())
    		{
    			//std::lock(m_mutex1, m_mutex2);
    
    			//std::lock_guard l2(m_mutex2, std::adopt_lock);
    			//std::lock_guard l1(m_mutex1, std::adopt_lock);
    
    			std::lock_guard<mutex> l1(m_mutex1);// 
    			std::lock_guard<mutex> l2(m_mutex2);
    			int num = m_list.front();
    			cout << "  num = " << num << endl;
    			m_list.pop_front();
    		}
    	}
    }
    
    
    
    int main()
    {
    
    
    	CReadAndWrite obj;
    	thread mywrite(&CReadAndWrite::wirte, &obj);
    	thread myread(&CReadAndWrite::read, &obj);
    
    	mywrite.join();
    	myread.join();
    
    	std::cout << "Main end!
    "
    ; }