程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> [並發並行]_[C/C++]_[使用線程本地存儲Thread Local Storage(TLS)調用復制文件接口的案例]

[並發並行]_[C/C++]_[使用線程本地存儲Thread Local Storage(TLS)調用復制文件接口的案例]

編輯:C++入門知識

[並發並行]_[C/C++]_[使用線程本地存儲Thread Local Storage(TLS)調用復制文件接口的案例]


 

使用場景:

1. 在復制文件時,一般都是一個線程調用一個接口復制文件,這時候需要緩存數據,如果每個文件都需要創建獨立的緩存,那麼內存碎片是很大的.

如果創建一個static的內存區,當多線程調用同一個接口時,多個線程同時使用同一個static緩存會造成數據污染.最好的辦法是這個緩存只對這個線程可見,

當線程創建時創建緩存區,當線程結束時銷毀緩存區.

2. 代碼裡有注釋:

test.cpp

 

#include 

#include pthread.h
#include 
#include 
#include 

typedef enum kTLSKey1
{
	kTLSKeyCopyFileBuf = 0,
	kTLSKeyOthers,
	kTLSKeyMax
}kTLSKey;

static pthread_key_t gTLSKey[kTLSKeyMax];
static int gTLSKeySize[kTLSKeyMax] = {4194304,4096};

// 這個只是測試等待線程全部結束用的,和TLS沒什麼關系.
static pthread_barrier_t barrier  = NULL; 
static int THREADCOUNT = 10;

// 我們自定義的庫提供的接口1
void StartWork(kTLSKey type)
{
	pthread_key_t& key = gTLSKey[type];
	pthread_key_create(&key,NULL);
}

// 我們自定義的庫提供的接口2
void EndWork(kTLSKey type)
{
	pthread_key_t& key = gTLSKey[type];
	pthread_key_delete(key);
}

// 我們自定義的庫提供的接口3
// data參數只是為了證明TLS的變量是綁定線程的.
void MyCopyFile(const char* from, const char* to,void* data)
{
	pthread_key_t& key = gTLSKey[kTLSKeyCopyFileBuf];
	char* lpvData = (char*)pthread_getspecific(key);
	assert(lpvData == data);

	Sleep(100);

}

void* ThreadFunc(void* data)
{
	int size = gTLSKeySize[kTLSKeyCopyFileBuf];
	pthread_key_t& key = gTLSKey[kTLSKeyCopyFileBuf];

	char* buf = (char*)malloc(size);
	std::cout << GetCurrentThreadId() << Create buf size:  << size << : << (int*)buf << std::endl;
	pthread_setspecific(key, buf); // 申請的內存存放到TLS裡.

	// 每個線程復制100個文件
	for (int i = 0; i < 100; ++i)
	{
		MyCopyFile(C:\infoworld.txt,E:\infoworld.txt,buf);
	}
	
	free(buf);
	std::cout << ThreadFunc:  << GetCurrentThreadId() <<  finish << std::endl;
	pthread_barrier_wait(&barrier);
	return NULL;
}

void TestPthreadLocalStorage()
{
	StartWork(kTLSKeyCopyFileBuf); // 在主程序初始化.
	pthread_barrier_init(&barrier,NULL, THREADCOUNT+1); // 主線程也是,所以+1

	// 模擬 THREADCOUNT 個線程同時調用接口 MyCopyFile.
	for (int i = 0; i < THREADCOUNT; ++i)
	{
		pthread_t t;  
        pthread_create(&t,NULL,ThreadFunc,NULL);  
        pthread_detach(t);
	}

	pthread_barrier_wait(&barrier);
	EndWork(kTLSKeyCopyFileBuf); // 在主程序釋放.
}

int main(int argc, char const *argv[])
{
	setvbuf(stdout,NULL,_IONBF,0);
	std::cout << test thread local storage. << std::endl;
	TestPthreadLocalStorage();
	std::cout << end thread local storage. << std::endl;

	return 0;
}

 

 

輸出:

 

test thread local storage.
5168 Create buf size: 4194304:0x1180020
3892 Create buf size: 4194304:0x1790020
3352 Create buf size: 4194304:0x21a0020
5808 Create buf size: 4194304:0x29b0020
4972 Create buf size: 4194304:0x2dc0020
6812 Create buf size: 4194304:0x31d0020
6132 Create buf size: 4194304:52200x35e0020 Create buf size: 
4194304:0x39f0020
6124 Create buf size: 4194304:0x3e00020
6864 Create buf size: 4194304:0x4210020
ThreadFunc: 5168 finish
ThreadFunc: 3892 finish
ThreadFunc: 6812 finish
ThreadFunc: 5220 finish
ThreadFunc: 4972 finish
ThreadFunc: 6132 finish
ThreadFunc: 6864 finish
ThreadFunc: 3352 finish
ThreadFunc: 5808 finish
ThreadFunc: 6124 finish
end thread local storage.

 

 

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