linux线程如何通信,linux线程通信(四)线程的属性

线程的高级属性

一次性初始化

有些时器需要且只能执行一次,比如互斥量初始化。如果库函数中有互斥量,使用一次初始会比较容易

一次性初始化 pthread_once_t变量,这个变量要用宏PTHREAD_ONCE_INIT初始化,然后创建一个与控制变量相关的初始化函数

pthread_once_t once_control = PTHREAD_ONCE_INIT;

void init-routine()

{

初始化互斥量

初始化读写锁

}

int pthread_once( pthread_once_t *once_contorl, void(*init_routine)(void));

多线程编译环境下,尽管 pthread_once出现在多个线程中国,但init_routine()函数只执行一次。

如果once-control初值为0 ,那么pthread_once 从未执行过,init_routine()函数会执行

如果once-control初值为1,则由于pthread_once都必须等待其中一个激发“已执行一次”信号,因此所有pthread_once()都会陷入永久等待,init_routine无法执行

如果once-control设为2,表示pthread_once已执行过一次,从而所有pthread_once都会立即返回,init_routine就没有际会之下

当pthread_once函数成功返回,once_control就会被设置为2.

#include "stdio.h"

#include "pthread.h"

#include "stdlib.h"

#include "signal.h"

#include "string.h"

#include "unistd.h"

pthread_once_t once =PTHREAD_ONCE_INIT;

void thread_init()

{

printf("i am in thread 0x%x\n",tid);

}

void *thread_fun1(void *arg)

{

tid =pthread_self;

printf("i am in thread 0x%x\n",tid);

printf("i am thread 0x%x\n",once); \\输出once是0

pthread_once(&once, thread_init);

printf("i am thread 0x%x\n",once); \\输出once是1

return NULL;

}

void *thread_fun2(void *arg)

{

sleep(2);

tid =pthread_self;

printf("i am in thread 0x%x\n",tid);

pthread_once(&once, thread_init);

return NULL;

}

int main()

{

pthread_t tid1,tid2;

int err;

err=pthread_create(&tid1,&attr,thread_fun1,NULL);

err=pthread_create(&tid2,NULL,thread_fun1,NULL);

pthread_join(tid1,NULL);

pthread_join(tid2,NULL);

}

线程的属性

线程的属性有哪些

线程的属性用pthread_attr_t类型的结构表示

cac95ffa5c79701825017eb2a2fc0548.png

并不是所有系统都支持线程的这些属性,需要检查当前系统是否支持你设置的属性。

还有一些属性不包含在pthread_attr_t结构体中,如:线程的可取消状态,取消类型,并发度。

int pthread_attr_init(pthread_attrT *attr);

-线程属性初始化

int pthread_attr_destroy(pthread_attr_t *attr)

-线程属性销毁

1.线程销毁会释放初始化时申请的内存空间

2.销毁函数还会用无效的初值初始化pthread_attr_t 对象,因此如果该属性对象被误用,会导致线程创建失败。

线程的同步属性

也包含互斥量,读写锁,条件变量的属性

int pthread_mutexattr_init(pthreaed_mutexattr_t *attr);

-互斥量初始化

int pthread_mutexattr_destroy(pthreaed_mutexattr_t *attr);

-互斥量销毁

进程的共享属性有两种值

PTHREAD_PROCESS_PRIVATE

-默认值,同一个进程中的多个线程访问同一个同步对象

PTHREAD_PROCESS_PRIVATE

-使互斥量在多个进程中进行同步,如果互斥量在多进程的共享内存区域,那么具有这个属性的互斥量可以同步多进程

设置互斥量进程共享属性

int pthread_mutexattr_getpshared(const pthread_mutexattr_t *resrtict attr, int *restrict pshared)

int pthread_mutexattr_setpshared(const pthread_mutexattr_t * attr, int pshared)

-进程共享属性通过检测宏_POSIX_THREAD_PROCESS_SHARED 得知系统是否支持

d0ac97b92670198b1c47ef2596b9a03f.png

设置互斥量的类型属性

int othreaed_mutex_gettype(const pthread_mutexattr_t *restrict attr, int *restrict type);

int othreaed_mutex_settype(const pthread_mutexattr_t * attr, int *type);

例:

78299f1e58af0a4ce2a83e8dadd92abb.png

#include "stdio.h"

#include "pthread.h"

#include "stdlib.h"

#include "string.h"

#include "unistd.h"

#include "fcntl.h"

#include "sys/mman.h"

#include "sys/stat.h"

int main()

{

char *shm ="myshm";

char *shm1 ="myshm1";

int shm_id,shm_id1; //一个共享内存存放数据,一个共享内存存放互斥量

char *buf;

pid_t pid;

pthread_mutex_t *mutex; //互斥量

pthread_mutexattr_t mutexattr; //互斥量属性

shm_id1 = shm_open(shm1 ,O_RDWR|O_CREAT, 0644); //打开共享内存

ftruncate(shm_id1, 100);//调整共享内存的大小

mutex = (pthread_mutex_t *)mmap(NULL,100,PROT_READ|PROT_WRITE,MAP_SHARED,shm_id1,0);//映射共享内存MAP_SHARED属性表面对共享内存的修改会影响其他进程,若映射成功则返回映射区的内存起始地址给mutex

pthread_mutexattr_init(&mutexattr);

#ifdef _POSIX_THREAD_PROCESS_SHARED

pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);

#endif

pthread_mutex_init(mutex, &mutexattr);

shm_id = shm_open(shm ,O_RDWR|O_CREAT, 0644);

ftruncate(shm_id, 100);

buf = (char *)mmap(NULL,100,PROT_READ|PROT_WRITE,MAP_SHARED,shm_id,0);

pid =fork();

if(pid==0)

{

sleep(1);//让父进程线运行

printf("i am child process\n");

pthread_mutex_lock(mutex);

memcpy(buf,"hello",6);

printf("child buf is :%s\n", buf);

pthread_mutex_unlock(mutex);

}

else if(pid>0)

{

printf("i am father process\n");

pthread_mutex_lock(mutex);

memcpy(buf,"world",6);

sleep(3);

printf("parent buf is :%s\n", buf);

pthread_mutex_unlock(mutex);

}

pthread_mutexattr_destroy(&mutexattr);

pthread_mutex_destroy(mutex);

munmap(buf,100);//解除映射

shm_unlink(shm);//消除共享内存

shm_unlink(shm1);

}

将互斥量的属性设置成线程共享的属性,就可以同步多进程了。

c8a235703316d5e0575d34d851548a52.png

线程的分离属性

分离属性:通知当前系统该线程结束时,其所属资源可以回收,没有被分离的则会保留它的虚拟内存,包括堆栈和其他系统资源。即僵尸进程。创建线程默认是非分离的。

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

-设置线程的分离属性

PTHREAD_CREATE_DETACHED 分离的

PTHREAD_CREATE_JOINABLE 非分离的

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

-获取线程的分离属性

设置线程分离属性的步骤

定义线程属性变量pthread_attr_t attr

初始化attr,pthread_attr_init(&attr)

设置线程为分离或非分离

线程创建pthread(&tid ,&attr ,thread_fun,NULL).

#include "stdio.h"

#include "pthread.h"

#include "stdlib.h"

#include "signal.h"

#include "string.h"

#include "unistd.h"

void *thread_fun1(void *arg)

{

printf("i am new thread1\n");

return(void *)1;

}

void *thread_fun2(void *arg)

{

printf("i am new thread2\n");

return(void *)2;

}

int main()

{

pthread_t tid1,tid2;

int err;

pthread_attr_t attr; //1.define

pthread_attr_init(&attr); //2.init

pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); //setdetcath

err=pthread_create(&tid1,&attr,thread_fun1,NULL); //分离pthread1

err=pthread_create(&tid2,NULL,thread_fun1,NULL);

err=pthread_join(tid1,NULL);

if(!err)

printf("join thread1 success\n"); //0是成功,非0是失败

else

printf("join thread1 failed\n");

err=pthread_join(tid2,NULL);

if(!err)

printf("join thread2 success\n");

else

printf("join thread2 failed\n");

}

e17829a5ea90635735ad0f839bc458b2.png

可见分离后不能连接了。

参数若为JOINABLE 都能连接成功

线程的栈属性

对于线程来说,虚拟地址空间的大小是固定的,线程中只有一个栈。但对线程来说,通有的虚拟地址被所有的线程共享。如果应用程序使用太多的线程,导致线程栈累计超过可用的虚拟地址空间,这个适合就要减少线程默认的栈大小。另外,如果线程分配了大量的自动变量或线程的栈帧太深,那么这个时候需要的栈要比默认的大。

如果虚拟地址用完了,可以使用malloc或mmap来为其他栈分配空间,并修改栈的位置

int pthread_attr_setstack(pthread_attr_t *attr ,void *stackaddr ,size_t stacksize);

-修改栈属性

int pthread_attr_getstack(pthread_attr_t *attr, void *stackaddr, size_t *stacksize)

-获取属性

stackaddr是栈的内存单元最低地址,但不一定是栈的开始。对于一些处理器,栈的地址是从高往低的,那么stackaddr是栈的结尾。

int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

int pthread_attr_getstacksize(pthread_attr_t *attr, size_t stacksize);

线程属性guardsize控制着线程末尾以后用以避免栈溢出的扩展内存的大小,这个属性默认是PAGESIZE个字节。

int pthread_attr_setguardsize(pthread_attr_t *attr, siez_t guardsize);

int pthread_attr_getguardsize(pthread_attr_t *attr, size)t *guaradsize)

#include "stdio.h"

#include "pthread.h"

#include "stdlib.h"

#include "signal.h"

#include "string.h"

#include "unistd.h"

#include "limits.h"

pthread_attr_t attr;

void *thread_fun1(void *arg)

{

size_t stacksize;

#ifdef _POSIX_THREAD_ATTR_STACKSIZE

pthread_attr_getstacksize(&attr, &stacksize);

printf("new thread stack size is %d\n",stacksize);

pthread_attr_setstacksize(&attr, 16389);

pthread_attr_getstacksize(&attr, &stacksize);

printf("new thread stack size is %d\n",stacksize);

#endif

return (void *)1;

}

int main()

{

pthread_t tid1;

int err;

pthread_attr_init(&attr);

pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);//可连接

#ifdef _POSIX_THREAD_ATTR_STACKSIZE

pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);//线程属性设定为最小堆栈 屏蔽掉这句就会输出默认的

#endif

err=pthread_create(&tid1,&attr,thread_fun1,NULL);

pthread_join(tid1,NULL);

return 0;

}

02b0d88af22ca8a530011ad06879c35f.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值