线程_验证线程间共享性(全局、静态、堆、文件描述符)

思路:是否允许共享关系到是否采用了写实拷贝技术;如果不允许共享,两个线程去读取同一个对象,这没问题(只读属性)。但是,如果,有一个进程想要去修改这个对象,操作系统会为该线程在他处拷贝一个新的对象以作修改之用。如果允许共享,那么这个对象始终只会有一份。这就是验证各种对象(全局、、静态、堆、文件描述符)是否共享的关键!

一、 全局

线程thr_fun1试图将全局数据n = 10000修改为n = 10。如果数据不共享,在线程thr_fun1打印输出n的值,然后在主线程main输出n的值,前后两者是不一样的。因为在线程thr_fun1修改n的值的时候,操作系统会为堆上另外开辟空间来供给thr_fun1使用。结果是这样吗——拭目以待!!!

#include
#include
#include

static int test = 10000;
int n = sizeof(test)/sizeof(int);

void* thr_fun1(void* arg)
{
    n = 10;
    printf("thr_fun1 thread is running! ");
    printf("n = %d\n", n);
}

int main()
{
    pthread_t tid;
    int err;
    err = pthread_create(&tid, NULL, thr_fun1, NULL);
    if(0 != err)
	    printf("can't create thread\n");
    pthread_join(tid, NULL);
    printf("main thread is running! ");
    printf("n = %d\n", n);
}

以一个静态整型变量n来充当全局数据,观察在线程thr_fun1修改了n的值之后,线程thr_fun1、主线程main先后打印输出n的值,如果结果为10(修改后), 10000(初始值)——不共享;如果结果为10(修改后), 10(修改后)——共享。从图1 可以看到,情况属于后者,验证出的结果是————共享!

线程_验证线程间共享性(全局、静态、堆、文件描述符)_第1张图片 图1 验证全局是否共享(linux平台)

二、 堆区 

思路:线程thr_fun1试图去修改主线程main在堆上申请的数组。如果不允许共享,那么在线程thr_fun1修改了数组之后;线程thr_fun1先打印该数组,主线程main后打印该数组,观察结果:

#include
#include
#include
#include
#include

typedef struct buf
{
    int* _arr;
    int _n;
}buf;

void print_arr(int* arr, int n)
{
    assert(NULL != arr);
    for(int i = 0; i < n; ++i)
	printf("%d ",arr[i]);
    printf("\n");
}

void* thr_fun1(void *arg)
{
    buf* buf = arg;
    buf->_arr[buf->_n - 1] = 100;	//如果不允许共享,main主线程输出将会与本线程不同;允许共享,则相同!
    printf("thr_fun1 is running! ");
    print_arr(buf->_arr, buf->_n);
}

int main()
{
    pthread_t tid;
    int err;
    int n = 10;
    
    int *arr = (int*)malloc(sizeof(int) * n);
    for(int i = 0; i < n; ++i)
	arr[i] = i+2;

    buf buf;
    buf._arr = arr;
    buf._n = n;

    err = pthread_create(&tid, NULL, thr_fun1, (void*)&buf);
    if(0 != err)
	printf("can't create thread\n");

    pthread_join(tid, NULL);	//main主线程不得先于其他线程之前结束,否则就会导致其他线程事务未处理完就退出了。

    printf("main thread is running! ");
    print_arr(buf._arr, buf._n);
}

分析过程和对待全局数据类似,从图2 可以看出:线程与线程之间,堆区数据是共享的! 

线程_验证线程间共享性(全局、静态、堆、文件描述符)_第2张图片 图2 测试堆区是否共享

三、 文件描述符 

说到文件描述符,就会提到浅拷贝以及读写偏移量的问题。如果是共享的,那么在pth_fun1线程从文本文件a.txt(内容是helloworld)读取5个字符之后,main主线程会接着pth_fun1线程上一次结束的位置开始继续读取;如果是不共享的,那么会从头开始读取。

运行结果预测:

  • 共享:pth_fun1线程输出hello,main主线程输出world。
  • 不共享:pth_fun1线程输出hello,main主线程也输出hello。
#include
#include
#include
#include
void* thr_fun1(void* arg)
{
    int fd = *(int*)arg;
    char buf[128] = {0};
    read(fd, buf, 5);
    printf("thr_fun1 thread is running : %s\n", buf);
}

int main()
{
    int fd = open("a.txt", O_RDWR | O_CREAT, 0664);
    write(fd, "helloworld", 10);
    lseek(fd, 0, SEEK_SET);
    pthread_t tid;
    int err;
    err = pthread_create(&tid, NULL, thr_fun1, (void*)&fd);
    if(0 != err)
	printf("can't create thread\n");
    pthread_join(tid, NULL);
    char buf[128] = {0};
    read(fd, buf, 5);
    printf("main thread is running : %s\n", buf);
}

从图3 我们可以看到,线程之前文件描述符是共享的,因为读写偏移量会相互影响。 

线程_验证线程间共享性(全局、静态、堆、文件描述符)_第3张图片 图3 验证描述符是否共享

你可能感兴趣的:(线程_验证线程间共享性(全局、静态、堆、文件描述符))