LinuxC多线程应用

1,简单线程程序的创建

线程的调度取决于调度器的策略,线程没有父子之称,是兄弟关系。有时候主线程先退出,那么次线程可能执行不到。所以一定要加上pthread_join()收尸

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>


static void * func(void *arg)
{
    puts("thread is working!");
    pthread_exit(NULL);
}


int main()
{
    pthread_t tid;
    int err;
    
    puts("Begin!");
    err = pthread_create(&tid, NULL , func, NULL);
    if(err)
    {
        fprintf(stderr, "pthread_create():%s\n",strerror(err));
        exit(1);
    }
    pthread_join(tid, NULL);
    puts("End!");
    exit(0);
}

2,循环打印abcd

方法1:如果互斥锁。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

#define THRNUM 4
static pthread_mutex_t mtx[THRNUM];

int next(int n)
{
	if((n+1) == THRNUM)
		return 0;
	else
		return n+1;
}

static void *thr_func(void *p)
{
	int n = (int)p;
	int c = 'a' + n;
	while(1)
	{
		pthread_mutex_lock(mtx+n);
		write(1, &c, 1);
		pthread_mutex_unlock(mtx+next(n));
	}
	pthread_exit(NULL);
}

int main()
{
	int i, err;
	pthread_t tid[THRNUM];
	
	alarm(1);
	for(i = 0; i < THRNUM; i++)
	{
		pthread_mutex_init(mtx+i, NULL);
		pthread_mutex_lock(mtx+i);
		err = pthread_create(tid+i, NULL, thr_func, (void *)i);
		if(err)
		{
			fprintf(stderr, "pthread_create():%s\n", strerror(err));
			exit(1);
		}
	}
	
	pthread_mutex_unlock(mtx+0);
	
	for(i=0; i<THRNUM; i++)
	{
		pthread_join(tid[i], NULL);
	}
	exit(0);
}

方法2,采用条件变量。全局变量加上条件变量

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

#define THRNUM 4
static pthread_mutex_t mtx;
static pthread_cond_t cond;
static int num = 0;

int next(int n)
{
	if((n+1) == THRNUM)
		return 0;
	else
		return n+1;
}

static void *thr_func(void *p)
{
	int n = (int)p;
	int c = 'a' + n;
	while(1)
	{
		pthread_mutex_lock(&mtx);
		while(num != n)
			pthread_cond_wait(&cond, &mtx);
		write(1, &c, 1);
		num = next(n);
		pthread_cond_broadcast(&cond);
		pthread_mutex_unlock(&mtx);
	}
	pthread_exit(NULL);
}

int main()
{
	int i, err;
	pthread_t tid[THRNUM];
	
	alarm(1);
	for(i = 0; i < THRNUM; i++)
	{
		
		err = pthread_create(tid+i, NULL, thr_func, (void *)i);
		if(err)
		{
			fprintf(stderr, "pthread_create():%s\n", strerror(err));
			exit(1);
		}
	}
	
	
	for(i=0; i<THRNUM; i++)
	{
		pthread_join(tid[i], NULL);
	}
	pthread_mutex_destroy(&mtx);
	pthread_cond_destroy(&cond);
	exit(0);
}

3,多线程版筛选质数

方法1,开辟200个线程同时工作。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

#define LEFT 30000000
#define RIGHT 30000200
#define THRNUM (RIGHT -LEFT)

struct thr_arg_st
{
	int n;
};

static void *thr_fun(void *p)
{
	int i, mark;
	int j = ((struct thr_arg_st *)p)->n;
	mark = 1;
	for(i = 2; i<j/2; i++)
	{
		if(j%i == 0)
		{
			mark = 0;
			break;
		}
	}
	if(mark)
	{
		printf("%d is primer\n", j);
	}
	pthread_exit(p);
}

int main()
{
	int i;
	int err;
	pthread_t tid[THRNUM];
	struct thr_arg_st *p;
	void *ptr;
	
	for(i = LEFT; i<RIGHT; i++)
	{
		p = malloc(sizeof(struct thr_arg_st));
		if(p == NULL)
		{
			perror("malloc");
			exit(1);
		}
		p->n = i;
		err = pthread_create(tid+(i-LEFT), NULL, thr_fun, p);
		if(err)
		{
			fprintf(stderr, "pthread_create():%s\n", strerror(err));
			exit(0);
		}	
	}
	
	for(i = 0; i<THRNUM; i++)
	{
		pthread_join(tid[i], &ptr);
		free(ptr);
	}
	
	exit(0);
}

方法2,指定线程个数,设置成线程池。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

#define LEFT 30000000
#define RIGHT 30000200
#define THRNUM 4

pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static int num = 0;

static void *thr_fun(void *p)
{
	int i, mark;
	int n = (int)p;
	
	while(1)
	{
		pthread_mutex_lock(&mtx);
		while(num == 0)
		{
			pthread_mutex_unlock(&mtx);
			sched_yield();
			pthread_mutex_lock(&mtx);
		}
		if(num == -1)
		{
			pthread_mutex_unlock(&mtx);//临界区里面的跳转要注意释放锁,否则会造成死锁。
			break;
		}
		int j = num;
		num = 0;
		pthread_mutex_unlock(&mtx);
		
		mark = 1;
		for(i = 2; i<j/2; i++)
		{
			if(j%i == 0)
			{
				mark = 0;
				break;
			}
		}
		if(mark)
		{
			printf("[%d]%d is primer\n", n, j);
		}
	}
	pthread_exit(NULL);
}

int main()
{
	int i;
	int err;
	pthread_t tid[THRNUM];
	
	for(i = 0; i<THRNUM; i++)
	{
		err = pthread_create(tid+i, NULL, thr_fun, (void*)i);
		if(err)
		{
			fprintf(stderr, "pthread_create():%s\n", strerror(err));
			exit(0);
		}	
	}
	
	for(i=LEFT; i<RIGHT; i++)
	{
		pthread_mutex_lock(&mtx);
		while(num > 0) //这里的逻辑有点不太懂
		{
			pthread_mutex_unlock(&mtx);
			sched_yield();
			pthread_mutex_lock(&mtx);
		}
		num = i;
		pthread_mutex_unlock(&mtx);
	}
	
	pthread_mutex_lock(&mtx);
	while(num != 0)
	{
		pthread_mutex_unlock(&mtx);
		sched_yield();
		pthread_mutex_lock(&mtx);
	}
	num = -1;
	pthread_mutex_unlock(&mtx);
	
	
	for(i = 0; i<THRNUM; i++)
	{
		pthread_join(tid[i], NULL);
	}
	pthread_mutex_destroy(&mtx);
	
	exit(0);
}

方法3,采用条件变量。避免循环抢锁等待抢锁等待

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

#define LEFT 30000000
#define RIGHT 30000200
#define THRNUM 4

pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static int num = 0;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

static void *thr_fun(void *p)
{
	int i, mark;
	int n = (int)p;
	
	while(1)
	{
		pthread_mutex_lock(&mtx);
		while(num == 0)
		{
			pthread_cond_wait(&cond, &mtx);
		}
		if(num == -1)
		{
			pthread_mutex_unlock(&mtx);//临界区里面的跳转要注意释放锁,否则会造成死锁。
			break;
		}
		int j = num;
		num = 0;
		pthread_cond_broadcast(&cond);
		pthread_mutex_unlock(&mtx);
		
		mark = 1;
		for(i = 2; i<j/2; i++)
		{
			if(j%i == 0)
			{
				mark = 0;
				break;
			}
		}
		if(mark)
		{
			printf("[%d]%d is primer\n", n, j);
		}
	}
	pthread_exit(NULL);
}

int main()
{
	int i;
	int err;
	pthread_t tid[THRNUM];
	
	for(i = 0; i<THRNUM; i++)
	{
		err = pthread_create(tid+i, NULL, thr_fun, (void*)i);
		if(err)
		{
			fprintf(stderr, "pthread_create():%s\n", strerror(err));
			exit(0);
		}	
	}
	
	for(i=LEFT; i<RIGHT; i++)
	{
		pthread_mutex_lock(&mtx);
		while(num > 0) //这里的逻辑有点不太懂
		{
			pthread_cond_wait(&cond, &mtx);
		}
		num = i;
		pthread_cond_signal(&cond);
		pthread_mutex_unlock(&mtx);
	}
	
	pthread_mutex_lock(&mtx);
	while(num != 0)
	{
		pthread_cond_wait(&cond, &mtx);
	}
	num = -1;
	pthread_cond_broadcast(&cond);
	pthread_mutex_unlock(&mtx);
	
	
	for(i = 0; i<THRNUM; i++)
	{
		pthread_join(tid[i], NULL);
	}
	pthread_mutex_destroy(&mtx);
	pthread_cond_destroy(&cond);
	
	exit(0);
}

4,令牌桶-用线程实现。

方法1,互斥量实现。忙等,查询法

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>


#include "mytbf.h"


static struct mytbf_st* job[MYTBF_MAX];
static pthread_mutex_t mut_job = PTHREAD_MUTEX_INITIALIZER;
static pthread_t tid_alarm;
static pthread_once_t init_once = PTHREAD_ONCE_INIT;


struct mytbf_st
{
    int cps;
    int burst;
    int token;
    int pos;
    pthread_mutex_t mut;
};


static void *thr_alarm(void *p)
{
    while(1)
    {
        pthread_mutex_lock(&mut_job);
        for (int i = 0; i < MYTBF_MAX; i++)
        {
            if(job[i] != NULL)
            {
                pthread_mutex_lock(&job[i]->mut);
                job[i]->token += job[i]->cps;
                if(job[i]->token > job[i]->burst)
                    job[i]->token = job[i]->burst;
                pthread_mutex_unlock(&job[i]->mut);
            }
        }
        pthread_mutex_unlock(&mut_job);
        sleep(1);
    }
    
}


static void module_unload(void)
{


    pthread_cancel(tid_alarm);
    pthread_join(tid_alarm, NULL);


    for (int i = 0; i < MYTBF_MAX; i++)
    {
        if(job[i] != NULL)
        {
            mytbf_destroy(job[i]);
        }
    }
    
    pthread_mutex_destroy(&mut_job);
}


static void module_load(void)
{
    
    int err;
    err = pthread_create(&tid_alarm, NULL, thr_alarm, NULL);
    if(err)
    {
        fprintf(stderr, "pthread_create():%s\n", strerror(err));
        exit(1);
    }


    // 钩子函数,程序结束前最后执行
    atexit(module_unload);
}


static int min(int a, int b)
{
    if(a < b)
        return a;
    return b;
}


static int get_free_pos_unlocked(void)
{
    for(int i = 0; i < MYTBF_MAX; i++)
    {
        if(job[i] == NULL)
            return i;
    }


    return -1;
}


mytbf_t *mytbf_init(int cps, int burst)
{
    struct mytbf_st *me;


    pthread_once(&init_once, module_load);


    me = malloc(sizeof(*me));
    if(me == NULL)
        return NULL;
    
    me->token = 0;
    me->cps = cps;
    me->burst = burst;
    pthread_mutex_init(&me->mut, NULL);


    pthread_mutex_lock(&mut_job);
    int pos = get_free_pos_unlocked();
    if(pos < 0)
    {
        pthread_mutex_unlock(&mut_job);
        free(me);
        return NULL;
    }


    me->pos = pos;
    job[pos] = me;
    pthread_mutex_unlock(&mut_job);


    return me;
}


int mytbf_fetchtoken(mytbf_t *ptr, int size)
{
    struct mytbf_st *me = ptr;
    int n;
    
    if(size <= 0)
        return -EINVAL;


    pthread_mutex_lock(&me->mut);
    while(me->token <= 0)
    {
        pthread_mutex_unlock(&me->mut);
        sched_yield();
        pthread_mutex_lock(&me->mut);
    }        


    n = min(me->token, size);
    me->token -= n;
    pthread_mutex_unlock(&me->mut);


    return n;
}


int mytbf_returntoken(mytbf_t *ptr, int size)
{
    struct mytbf_st *me = ptr;


    if(size <= 0)
        return -EINVAL;


    pthread_mutex_lock(&me->mut);
    me->token += size;
    if(me->token > me->burst)
        me->token = me->burst;
    pthread_mutex_unlock(&me->mut);


    return size;
}


int mytbf_destroy(mytbf_t *ptr)
{
    
    struct mytbf_st *me = ptr;
    pthread_mutex_lock(&mut_job);
    job[me->pos] = NULL;
    pthread_mutex_unlock(&mut_job);


    pthread_mutex_destroy(&me->mut);
    free(ptr);


}

方法2,条件变量,取消忙等。查询法

pthread_cond_wait()死锁-》等待(当有signal,抢锁查看条件)

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sched.h>

#include "mytbf.h"

static struct  mytbf_st *job[MYTBF_MAX];
static pthread_mutex_t mtx_job = PTHREAD_MUTEX_INITIALIZER;

struct mytbf_st
{
    int cps;
    int token;
    int burst;
    int pos;
    pthread_mutex_t mtx;
    pthread_cond_t cond;
};

static pthread_once_t init_once;
static pthread_t tid_alrm;

static int getpos_unlock()
{
    int i;
    for(i = 0; i<MYTBF_MAX; i++)
    {
        if(job[i]== NULL)
            return i;
    }
    return -1;
}

static void * thr_handler(void * s)
{
    int i;
    
    while(1)
    {
        pthread_mutex_lock(&mtx_job);
        for(i=0; i<MYTBF_MAX; i++)
        {
            if(job[i] != NULL)
            {
                pthread_mutex_lock(&job[i]->mtx);
                job[i]->token += job[i]->cps;
                if(job[i]->token > job[i]->burst)
                    job[i]->token = job[i]->burst;
                pthread_cond_broadcast(&job[i]->cond);
                pthread_mutex_unlock(&job[i]->mtx);
            }
        }
        pthread_mutex_unlock(&mtx_job);
        sleep(1);
    }
}


static void module_unload(void )
{
    int i;
    
    pthread_cancel(tid_alrm);
    pthread_join(tid_alrm, NULL);
    
    for(i=0; i<MYTBF_MAX; i++)
    {
        if(job[i] != NULL)
        {
            mytbf_destory(job[i]);
        }
    }
    pthread_mutex_destroy(&mtx_job);
}


static void module_load()
{
    //sighandler_save = signal(SIGALRM, alrm_handler);  //保存sigalrm处理函数原来的处理方式
    //alarm(1);
    
    int err;
    err = pthread_create(&tid_alrm, NULL, thr_handler, NULL);
    if(err)
    {
        fprintf(stderr, "pthread_create():%s", strerror(err));
        exit(1);
    }
    atexit(module_unload);
}


mytbf_t *mytbf_init(int cps , int burst)
{
    struct mytbf_st *me;
    int pos;
    
    pthread_once(&init_once, module_load);
    
    me = malloc(sizeof(*me));
    if(me == NULL)
        return NULL;
    
    me->cps = cps;
    me->token = 0;
    me->burst = burst;
    pthread_mutex_init(&me->mtx, NULL);    
    pthread_cond_init(&me->cond, NULL);
    
    pthread_mutex_lock(&mtx_job);
    pos = getpos_unlock();
    if(pos < 0)
    {
        pthread_mutex_unlock(&mtx_job);
        return NULL;
    }
    me->pos = pos;
    job[pos] = me;
    pthread_mutex_unlock(&mtx_job);
    
    return me;  //没加返回值,报错了。
}


static int min(int a, int b)
{
    if(a<b)
        return a;
    return b;
}


int mytbf_fetchtoken(mytbf_t *ptr, int size) // 取token
{
    struct mytbf_st *me = ptr;
    int n;
    
    if(size <= 0)
        return -EINVAL;
    
    pthread_mutex_lock(&me->mtx);
    while(me->token <= 0)
    {
        //pause();
        pthread_cond_wait(&me->cond, &me->mtx);
    }
    n = min(me->token, size);
    
    me->token -= n;
    pthread_mutex_unlock(&me->mtx);
    
    return n;
}


int mytbf_returntoken(mytbf_t *ptr, int size)
{
    struct mytbf_st *me = ptr;
    if(size <=0 )
        return -EINVAL;
    
    pthread_mutex_lock(&me->mtx);
    me->token += size;
    if(me->token > me->burst)
        me->token = me->burst;
    pthread_cond_broadcast(&me->cond);
    pthread_mutex_unlock(&me->mtx);
    
    return size;
}


void mytbf_destory(mytbf_t *ptr)
{
    struct mytbf_st *me = ptr;
    pthread_mutex_lock(&mtx_job);
    job[me->pos] = NULL;
    pthread_mutex_unlock(&mtx_job);
    pthread_mutex_destroy(&me->mtx);
    pthread_cond_destroy(&me->cond);
    free(me);
}

5,利用互斥量和条件变量实现信号量

功能:始终保持5个线程在工作

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>

#include "mysem.h"
struct mysem_st
{
	int value;
	pthread_mutex_t mtx;
	pthread_cond_t cond;
};


mysem_t * mysem_init(int value)
{
	struct mysem_st *me;
	
	me = malloc(sizeof(*me));
	if(me == NULL)
		return me;
	
	me->value = value;
	pthread_mutex_init(&me->mtx, NULL);
	pthread_cond_init(&me->cond, NULL);
	
	return me;
}

int mysem_add(mysem_t *ptr, int n)
{
	struct mysem_st *me = ptr;
	if(ptr == NULL)
		return -EINVAL;
	
	pthread_mutex_lock(&me->mtx);
	me->value += n;
	pthread_cond_broadcast(&me->cond);
	pthread_mutex_unlock(&me->mtx);
	return 0;
}

int mysem_sub(mysem_t *ptr, int n)
{
	struct mysem_st *me = ptr;
	pthread_mutex_lock(&me->mtx);
	while(me->value < n)
		pthread_cond_wait(&me->cond, &me->mtx);  //解锁,等待,等broadcast。
	me->value -= n;
	pthread_mutex_unlock(&me->mtx);
	return 0;
}

int mysem_destroy(mysem_t *ptr)
{
	struct mysem_st *me = ptr;
	
	pthread_cond_destroy(&me->cond);
	pthread_mutex_destroy(&me->mtx);
	
	free(me);
	return 0;
}

main文件

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

#include "mysem.h"

#define LEFT 30000000
#define RIGHT 30000200
#define THRNUM 4
static mysem_t *mysem;

static void *thr_fun(void *p)
{
	int i, mark;
	int j = (int)p;
	mark = 1;
	for(i = 2; i<j/2; i++)
	{
		if(j%i == 0)
		{
			mark = 0;
			break;
		}
	}
	if(mark)
	{
		printf("%d is primer\n", j);
	}
	sleep(2);
	mysem_add(mysem, 1);
	pthread_exit(NULL);
}

int main()
{
	int i;
	int err;
	pthread_t tid[RIGHT-LEFT];
	
	mysem = mysem_init(THRNUM);
	
	
	for(i = LEFT; i<RIGHT; i++)
	{
		mysem_sub(mysem, 1); 
		err = pthread_create(tid+i-LEFT, NULL, thr_fun, (void *)i);
		if(err)
		{
			fprintf(stderr, "pthread_create():%s\n", strerror(err));
			exit(0);
		}	
	}
	
	for(i = LEFT; i<RIGHT; i++)
	{
		pthread_join(tid[i-LEFT], NULL);
	}
	mysem_destroy(mysem);
	
	exit(0);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux C多线程编程是指在Linux系统下使用C语言进行多线程编程的实践。多线程编程的目的在于提高程序的效率,增强程序的并发性和响应性。下面举个实例说明多线程编程的应用。 假设有一个简单的程序需要处理大量的文本数据,要求计算文本中出现某个关键字的次数,并将结果输出到文件中。如果采用单线程方式来实现,可能会因为数据量过大而导致程序运行缓慢,甚至崩溃。而采用多线程方式,可以将数据分成多个块,分别进行关键字统计和输出操作,从而提高程序的效率和响应速度。 实现多线程编程的关键在于线程之间的同步和互斥。我们可以使用pthread库提供的函数来实现线程的创建、销毁、同步和互斥。pthread_create()函数用于创建新的线程,pthread_join()函数用于等待线程结束并获取其返回值。pthread_mutex_init()函数和pthread_mutex_lock()、pthread_mutex_unlock()函数用于实现线程之间的互斥。通过使用这些函数,我们可以在程序中实现多线程编程。 在实际应用多线程编程时,我们需要注意以下几点:首先,要根据实际情况设置合适的线程数以避免资源的浪费和线程的阻塞;其次,要注意线程之间的同步和互斥,避免出现竞争条件和死锁等问题;最后,要注意内存管理和异常处理等问题,保证程序的稳定性和可靠性。 综上所述,Linux C多线程编程是提高程序效率和响应速度的有效手段,并需要注意线程之间的同步和互斥问题。在实践中,我们需要结合实际应用情况合理设置线程数,处理好同步和互斥问题,并注意内存管理和异常处理等问题,以保证程序的稳定性和可靠性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值