程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> [並發並行]_[初級]_[C++實現sychronized方式的對象鎖]

[並發並行]_[初級]_[C++實現sychronized方式的對象鎖]

編輯:關於C++

 

場景:

1. 多線程程序, 數據如果在多線程間共享時, 比如數組, 基本都是需要加鎖來保證安全,正確性. std庫的數據結構類,如std::vector不是線程安全的, 所以讀寫時必須上鎖.

2. objc,Java可以用sychronized來對對象加鎖, 使能安全訪問對象, 如果不加鎖, 大多數情況下程序會崩潰.

3. 問題是無論是用 pthread_mutex_t 還是用CriticalSection, 都需要額外創建一個mutex和section來進行加鎖,這樣會增加很多全局變量

(需要在不同的源代碼裡使用鎖,只能是全局變量), 使用不方便還容易出錯.

4. 這裡設計了一個AALock類, 功能類似synchronize 關鍵字, 對對象加鎖. 本質就是用一個map來進行object->mutex的映射加鎖.

5. pthread win32 也可以換成CriticalSection, 自己改吧.

aa_lock.h

 

#ifndef __AA_LOCK_H
#define __AA_LOCK_H

class  AALock
{
public:
	AALock(void* object);
	~AALock();

	static void GLock(void* object);
	static void GUnLock(void* object);

private:
	void* lock_object_;
};

#endif

 

 

aa_lock.cpp

 

#include aa_lock.h
#include pthread.h
#include 
typedef void* LockObject; // 重點是這裡,用map來作為mutex的映射,雖然會損失點性能,但是使用方便. static std::map gLockObject; pthread_mutex_t gMapMutex = NULL; class AALockInternal { public: AALockInternal() { pthread_mutex_init(&gMapMutex,NULL); } ~AALockInternal() { pthread_mutex_destroy(&gMapMutex); } }; static AALockInternal gLockInternal; AALock::AALock(void* object) { lock_object_ = object; GLock(object); } AALock::~AALock() { GUnLock(lock_object_); } void AALock::GLock(void* object) { pthread_mutex_lock(&gMapMutex); pthread_mutex_t lock = NULL; if(gLockObject.find(object)!=gLockObject.end()) { lock = gLockObject[object]; }else { pthread_mutex_t temp = NULL; pthread_mutex_init(&temp,NULL); gLockObject[object] = temp; lock = temp; } pthread_mutex_unlock(&gMapMutex); pthread_mutex_lock(&lock); } void AALock::GUnLock(void* object) { pthread_mutex_lock(&gMapMutex); pthread_mutex_t lock = NULL; lock = gLockObject[object]; pthread_mutex_unlock(&gMapMutex); pthread_mutex_unlock(&lock); }
test.cpp

 

 

#include pthread.h

#include 
#include 
#include 
#include 
#include 
#include 
#include aa_lock.h

static const int gMaxCountTime = 10000;
static const int gTextThreadNum = 100;
static pthread_t ts[gTextThreadNum];
static int64_t gCount = 0;
static std::vector gCountArray;

void* StartPthread(void* data)
{
	for (int i = 0; i < gMaxCountTime; ++i)
	{
		// 去掉鎖的話,下邊的assert隨時crash.
		// 可對對象加鎖,類似objc或Java的同步關鍵字sychronized
		AALock::GLock(&gCount);
		++gCount;
		AALock::GUnLock(&gCount);

		// 去掉鎖,push_back隨時崩潰,因為vector並不是線程安全的.
		AALock::GLock(&gCountArray);
		gCountArray.push_back(i);
		AALock::GUnLock(&gCountArray);
	}

	return NULL;
}

void TestAALock()
{
	for (int i = 0; i < gTextThreadNum; ++i)
	{
		pthread_create(&ts[i],NULL,StartPthread,NULL);
	}

	for (int i = 0; i < gTextThreadNum; ++i)
	{
		pthread_join(ts[i],NULL);		
	}

	std::cout << gCount:  << gCount << std::endl;
	assert(gCount == gMaxCountTime*gTextThreadNum);

	std::cout << gCountArray size:  << gCountArray.size() << std::endl; 
	assert(gCount == gCountArray.size());
}

int main(int argc, char const *argv[])
{
	
	for (int i = 0; i < 10; ++i)
	{
		TestAALock();
		gCount = 0;
		gCountArray.clear();
	}
	

	return 0;
}

輸出:

 

 

C:Usersapple2Desktop	est>test
gCount: 1000000
gCountArray size: 1000000
gCount: 1000000
gCountArray size: 1000000
gCount: 1000000
gCountArray size: 1000000
gCount: 1000000
gCountArray size: 1000000
gCount: 1000000
gCountArray size: 1000000
gCount: 1000000
gCountArray size: 1000000
gCount: 1000000
gCountArray size: 1000000
gCount: 1000000
gCountArray size: 1000000
gCount: 1000000
gCountArray size: 1000000
gCount: 1000000
gCountArray size: 1000000
 


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved