有些时器需要且只能执行一次,比如互斥量初始化。如果库函数中有互斥量,使用一次初始会比较容易
一次性初始化 pthread_once_t变量,这个变量要用宏PTHREAD_ONCE_INIT初始化,然后创建一个与控制变量相关的初始化函数
#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类型的结构表示
并不是所有系统都支持线程的这些属性,需要检查当前系统是否支持你设置的属性。
还有一些属性不包含在pthread_attr_t结构体中,如:线程的可取消状态,取消类型,并发度。
也包含互斥量,读写锁,条件变量的属性
进程的共享属性有两种值
设置互斥量进程共享属性
#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);
}
分离属性:通知当前系统该线程结束时,其所属资源可以回收,没有被分离的则会保留它的虚拟内存,包括堆栈和其他系统资源。即僵尸进程。创建线程默认是非分离的。
设置线程分离属性的步骤
#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");
}
可见分离后不能连接了。
参数若为JOINABLE 都能连接成功
对于线程来说,虚拟地址空间的大小是固定的,线程中只有一个栈。但对线程来说,通有的虚拟地址被所有的线程共享。如果应用程序使用太多的线程,导致线程栈累计超过可用的虚拟地址空间,这个适合就要减少线程默认的栈大小。另外,如果线程分配了大量的自动变量或线程的栈帧太深,那么这个时候需要的栈要比默认的大。
如果虚拟地址用完了,可以使用malloc或mmap来为其他栈分配空间,并修改栈的位置
线程属性guardsize控制着线程末尾以后用以避免栈溢出的扩展内存的大小,这个属性默认是PAGESIZE个字节。
#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;
}