线程作为一个重要的编程模型,在服务类程序中大量的使用。并发、同步等概念大家都耳熟能详。
一个进程中的线程共享同样的资源,在一般情况下不会存在问题,但是当对每个线程要有特殊的属性时,
就会存在问题,例如函数修改一个在堆上分配的buff,此时不同的线程调用该函数时,都会对这个buff进行
修改。这样,数据的一致性就得不到保证。
线程似有变量给这个问题提供了解决方案。一下是一段C++代码,使用基于linux系统,使用线程私有数据
模型。
-
/*************************************************************
-
* 用于学习使用线程似有数据的使用,同样的一个key,对不同的线程
-
* 关联到不同的数据对象,使用相应的 get 和 set 加上 key 操作这
-
* 个数据。
-
*
-
* dinglonglong
-
* 2012-08-11
-
* **********************************************************/
-
#include <pthread.h>
-
#include <unistd.h>
-
#include <cstring>
-
#include <cstdio>
-
#include <cstdlib>
-
-
pthread_key_t key;
-
pthread_once_t init_done = PTHREAD_ONCE_INIT;
-
-
/**
-
* 初始化key
-
*/
-
void thread_init()
-
{
-
pthread_key_create(&key, free);
-
}
-
-
/**
-
* 向现成的buff中写数据
-
*/
-
char* init_buff(char* prex, int index)
-
{
-
char* buff = (char*)pthread_getspecific(key);
-
if (buff == NULL) {
-
buff = (char*)malloc(strlen(prex) + 2);
-
pthread_setspecific(key, buff);
-
}
-
-
sprintf(buff, "%s:%d", prex, index);
-
return buff;
-
}
-
-
/**
-
* 线程函数
-
*/
-
void* tf(void* arg)
-
{
-
pthread_once(&init_done, thread_init);
-
-
for (int i = 0; i < 10; i++) {
-
char* res = init_buff((char*)arg, i);
-
printf("%s\n", res);
-
-
sleep(1);
-
}
-
-
return NULL;
-
}
-
-
/**
-
* test
-
*/
-
int main(int argc, char* argv[])
-
{
-
void* ret;
-
char* name_1 = (char*)"thread_1";
-
char* name_2 = (char*)"thread_2";
-
pthread_t pt_1;
-
pthread_t pt_2;
-
-
pthread_create(&pt_1, NULL, tf, name_1);
-
pthread_create(&pt_2, NULL, tf, name_2);
-
-
pthread_join(pt_1, &ret);
-
pthread_join(pt_2, &ret);
-
-
printf("main over.\n");
-
-
return 0;
-
}
// 编译:g++ -lpthread test.cpp -o test
// 运行结果:
thread_2:0
thread_1:0
thread_2:1
thread_1:1
thread_2:2
thread_1:2
thread_2:3
thread_1:3
thread_2:4
thread_1:4
thread_1:5
thread_2:5
thread_2:6
thread_1:6
thread_2:7
thread_1:7
thread_1:8
thread_2:8
thread_2:9
thread_1:9
main over.
使用init_thread函数创建key,在每个线程中,用这个key去取buff,如果没有则malloc一个,pthread_once
保证这个key只被创建一次,避免初始化时的竞争。
从打印可以看出,每个线程使用自己的buff,彼此之间没有冲突。
同样对java来说,也存在线程私有变量的说法,java代码如下:
-
public class TestThreadLoacl extends Thread {
-
public static ThreadLocal<String> threadLocal = new ThreadLocal<String>();
-
-
private String name;
-
-
public TestThreadLoacl(String name) {
-
this.name = name;
-
}
-
-
public void run() {
-
for (int i = 0; i < 10; i++) {
-
System.out.println(threadLocal.get());
-
threadLocal.set(name + " set value: " + i);
-
-
try {
-
Thread.sleep(1000);
-
} catch (InterruptedException e) {
-
e.printStackTrace();
-
}
-
}
-
}
-
-
/**
-
* main test
-
*/
-
public static void main(String[] args) {
-
threadLocal.set("main set value: main.");
-
-
(new TestThreadLoacl("Thread_1")).start();
-
(new TestThreadLoacl("Thread_2")).start();
-
}
-
}
// 运行结果:
null
null
Thread_1 set value: 0
Thread_2 set value: 0
Thread_1 set value: 1
Thread_2 set value: 1
Thread_1 set value: 2
Thread_2 set value: 2
Thread_1 set value: 3
Thread_2 set value: 3
Thread_1 set value: 4
Thread_2 set value: 4
Thread_1 set value: 5
Thread_2 set value: 5
Thread_1 set value: 6
Thread_2 set value: 6
Thread_1 set value: 7
Thread_2 set value: 7
Thread_1 set value: 8
Thread_2 set value: 8
阅读(2630) | 评论(0) | 转发(0) |