多线程编程一:线程基础函数
五个线程函数
1、线程的创建 int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start routine)(void *), void *arg ) |
函数返回值为0表示创建成功 |
2、线程的终止: void pthread_exit(void *retval) |
终止方式有3种,① 线程调用pthread_exit函数,类似于进程的exit函数;② 线程被同一进程的其他线程取消; ③ 线程从启动例程返回。 |
3、线程的等待: int pthread_join(pthread_t thread, void **retval) |
调用pthread_join函数等待线程tid的结束,并获取传递的参数,函数返回值为0表示连接成功 |
4、线程的取消: int pthread_cancel(pthread_t thread); |
pthread_cancel调用并不等待线程终止,它只提出请求。线程在取消请求(pthread_cancel)发出后会继续运行,直到到达某个取消点(CancellationPoint)。函数返回值为0表示取消成功 |
5、线程的分离: int pthread_detach(pthread_t thread); |
pthread_detach()函数可以理解成main线程想把创建的线程寄养出去,不再调用pthread_join函数进行回收。函数返回值为0表示分离成功 |
线程函数的调用:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
static void cleanup_func(void *q)
{
puts(q);
}
static void *func(void *p)
{
puts("Thread is working!\r\n");
// 挂钩子函数cleanup_func()
pthread_cleanup_push(cleanup_func, "cleanup:1");
pthread_cleanup_push(cleanup_func, "cleanup:2");
pthread_cleanup_push(cleanup_func, "cleanup:3");
puts("push over!\r\n");
/* 参数1表示执行,0表示不执行 */
pthread_cleanup_pop(1);
pthread_cleanup_pop(1);
pthread_cleanup_pop(0);
/*pthread_exit结束线程*/
pthread_exit(NULL);
}
int main()
{
pthread_t tid;
int errornum = 0;
puts("Begin:\r\n");
/*pthread_create创建线程tid*/
errornum = pthread_create(&tid, NULL, func, NULL);
if(errornum)
{
printf("pthread_create failed...\r\n");
}
/*pthread_join等待创建的兄弟线程tid的结束并回收*/
pthread_join(tid,NULL);
puts("End!");
return 0;
}
编写好pthread.c文件后,通过gcc thread.c -o thread -lpthread进行编译,并./thread运行
利用多线程筛质数
利用多线程筛质数 #include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define MIN 10
#define MAX 100
#define THRDNUM (MAX - MIN + 1)
static void *primer_func(void *p)
{
int i = 0;
int j = 0;
int mark = 1;
i = *(int *)p;
for(j = 2; j<= i/2; j++)
{
if(0 == (i%j))
{
mark = 0;
}
}
if(mark == 1)
{
printf("Number %d is a primer!\r\n", i);
}
pthread_exit(NULL);
}
int main()
{
int i = 0;
int errnum = 0;
pthread_t tid[THRDNUM];
for(i = MIN; i<= MAX; i++)
{
errnum = pthread_create( tid + i - MIN, NULL, primer_func, &i);
if(0 != errnum)
{
puts("pthread_create failed\r\n");
exit(1);
}
}
for(i = MIN; i<= MAX; i++)
{
pthread_join(tid[i-MIN],NULL);
}
exit(0);
}
经过编译运行得到下面的结果:而本应该的结果应该是11、13、17、19、23、29、31、37、41、43、47、53、59、61、67、71、73、79、83、89、97共21个质数,很明显是算错了。
重新编译运行结果如下:
这次是对的,但是再次重新编译运行又会出现错误的结果如下
这种现象的原因是多线程发生了竞争,竞争原因是创建的多个线程访问传入 i 的地址是一样的,这样就会有冲突,解决方案如下:
通过结构体临时分配内存解决线程竞争的问题 #include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define MIN 10
#define MAX 100
#define THRDNUM (MAX - MIN + 1)
typedef struct thread_arg_st
{
int n;
}THREAD_ARG_S;
static void *primer_func(void *p)
{
int i = 0;
int j = 0;
int mark = 1;
THREAD_ARG_S *pstThrArg = NULL;
pstThrArg = (THREAD_ARG_S *)p;
i = (pstThrArg->n);
for(j = 2; j<= i/2; j++)
{
if(0 == (i%j))
{
mark = 0;
}
}
if(mark == 1)
{
printf("Number %d is a primer!\r\n", i);
}
pthread_exit(p);
}
int main()
{
int i = 0;
int errnum = 0;
pthread_t tid[THRDNUM];
THREAD_ARG_S *pstThrArg;
void *ptr;
for(i = MIN; i<= MAX; i++)
{
pstThrArg = malloc(sizeof(pstThrArg));
if(NULL == pstThrArg)
{
printf("malloc failed!");
exit(0);
}
pstThrArg->n = i;
errnum = pthread_create( tid + i - MIN, NULL, primer_func, pstThrArg);
if(0 != errnum)
{
puts("pthread_create failed\r\n");
exit(1);
}
}
for(i = MIN; i<= MAX; i++)
{
pthread_join(tid[i-MIN],&ptr);
free(ptr);
}
exit(0);
}
除了用结构体传参外,还可以通过数组的方式避免地址竞争问题
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define MIN 10
#define MAX 100
#define THRDNUM (MAX - MIN + 1)
static void *primer_func(void *p)
{
int i = 0;
int j = 0;
int mark = 1;
i = *(int *)(p);
for(j = 2; j<= i/2; j++)
{
if(0 == (i%j))
{
mark = 0;
}
}
if(mark == 1)
{
printf("Number %d is a primer!\r\n", i);
}
pthread_exit(NULL);
}
int main()
{
int i = 0;
int errnum = 0;
pthread_t tid[THRDNUM];
int array[THRDNUM]={0};
void *ptr;
int cnt = 0;
for(i = MIN; i<= MAX; i++)
{
array[cnt] = i;
errnum = pthread_create( tid + i - MIN, NULL, primer_func, (array+cnt));
if(0 != errnum)
{
puts("pthread_create failed\r\n");
exit(1);
}
++cnt;
}
for(i = MIN; i<= MAX; i++)
{
pthread_join(tid[i-MIN],NULL);
}
exit(0);
}