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);
}