[并发并行]_[初级]_[C++实现sychronized方式的对象锁]


场景:

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 <map>

typedef void* LockObject;
// 重点是这里,用map来作为mutex的映射,虽然会损失点性能,但是使用方便.
static std::map<void*,pthread_mutex_t> 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 <stdlib.h>
#include <iostream>
#include <stdint.h>
#include <assert.h>
#include <string>
#include <vector>
#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<int> 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:\Users\apple2\Desktop\test>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

完整项目下载地址:

http://download.csdn.net/detail/infoworld/9327825



你可能感兴趣的:(C++,Lock,mutex,对象锁,synchronize)