多线程编程一:线程基础函数

五个线程函数

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表示分离成功

线程函数的调用:

thread.c文件演示线程函数的调用
 #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);
}

 

posted @ 2023-02-03 16:05  轩邈、  阅读(49)  评论(0编辑  收藏  举报