筛质数的例子 201个进程。用指定n个进程筛质数。
cp ../../process_basic/primer0.c ./放到当前路径下
现在的计算范围,thrnum :right-left右边界-左边界
- 思路:main当中,一个人干活 计算,现在希望每有一个待计算的i值用一个线程去做 for循环里的工作 用一个函数。main创建线程 兄弟 没有主次之分。
int main()
{
int i,err;
pthread_t tid[THRNUM]; //需要的参数 create
for(i=LEFT;i<=RIGHT;i++)
{
err=pthread_create(&tid+(i-LEFT),NULL,thr_prime,&i);
if(err)
{
fprintf(stderr,"pthread_create():%s\n",stderror(err));
exit(1); //join 收尸 如果 最后一个线程失败 需要将前面的回收资源
}
}
//收尸
for(i=LEFT;i<=RIGHT;i++)
pthread_join(tid[i-LEFT],NULL);
exit(0);
}
static void *thr_prime(void *p)
{
int i,j,mark;
i = *(int *)p;
mark=1;
//是质数的话输出 不是的话算了
for(j=2; j<i/2;j++)
{
if(i%j == 0)
{
mark=0;
break;
}
}
if(mark)
printf("%d is a primer\n",i);
pthread_exit(NULL);
}
出现竞争 ,非原子操作。
协议 大家的约定。
十字路口 没有红绿灯,两辆车 南北 东西方向
车什么时候到来不知道 异步事件 什么
竞争:在没有约定的情况下 大家在抢同一个资源在用。十字路口 资源 两辆车 不知道是否相撞 无法预料。如何让两辆车不相撞?
最好不要用sleep 无法解决两个问题 等什么 等多久; 哲学问题
那如何让两辆车相撞?加长车长度,sleep 调试手段让线程存在时间增长 等待 测试 。
ps ax -L
错误:地址传参,i 一块地址 用201个指针指向这一块空间 201个人在用同一个地址 传值 可以 丑陋的办法 强转 void* i
看是否有各种形式的退出。 并发:顺序不是 从小到大
./primer0 |wc -l
继续改进:不要强转 201个i在201个空间 捏一个结构体 考虑动态分配 传结构体类型指针
struct thr_arg_st
{
int n;
};
for
struct thr_arg_st *p;
p=malloc(sizeof(*p));
if(p==NULL)
{
perror("malloc()");
exit(1);
}
p->n=i;
err=pthread_create(tid+(i-LEFT),NULL,thr_prime,p);
i = (struct thr_arg_st*)p->n;
free(p);但这样做也不好,希望malloc和free在用一个函数当中 或者同一个模块
改 pthread_join pthread_exit 传p
void *ptr;
for(i=LEFT;i<=RIGHT;i++)
{
pthread_join(tid[i-LEFT],&ptr);
free(ptr)
}
---
pthread_exit(p);一个进程中能够创建出的线程个数?
一个函数扔出去很多次,代码段公用 栈独立
ulimt -a 栈 大小
虚拟空间大小,需要看当前空间里可以创建多少10m的栈。取决于外在的资源量。64位 是tid先 消耗掉。128t
资源数 有上限。
main负责创建20个线程,threadnum- 扔出去20个线程运行,相应的收尸环节
- 每一个线程完成的任务 thr_add
- 提前把1放到
/tmp/out文件中去 使用命令echo 1 > /tmp/out使用 cat 查看 - atoi字符转为整型
- sleep(1) 放大竞争,两辆车相撞的机率,一开始不大,而我们把机身拉长。。。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define THRNUM 20
#define FNAME "/tmp/out"
#define LINESIZE 1024
//每个线程完成的任务: 打开 读数 加一 写回 关闭
static void *thr_add(void *p)
{
FILE *fp;
char linebuf[LINESIZE];
fp=fopen(FNAME,"r+");
if(fp==NULL)
{
//打开失败,报错结束
perror("fopen()");
exit(1)
}
fgets(linebuf,LINESIZE,fp);
//文件指针定位
fseek(fp,0,SEEK_SET);
//放大故障,竞争
sleep(1);
fprintf(fp,“%d\n”atoi(linebuf)+1);
fclose(fp);
pthread_exit(NULL);
}
int main()
{
//线程标识数组
pthread_t tid[THRNUM];
//for循环创建 调用函数创建
for(i=0;i<THRNUM;i++)
{
err=pthread_create(tid+i,NULL,thr_add,NULL);
if(err)
{
fprintf(stderr,"pthread_create():%s\n",strerror(err));
exit(1);
}
}
for(i=0;i<THRNUM;i++)
pthread_join(tid[i],NULL);
exit(0);
}- mutex的创建和销毁,限制文件的操作是互斥的
- 加入lock lock限制代码能否运行
//互斥量
static pthread_mutex_t mut = PTHREAD_MUTEXINITIALIZER;
pthread_mutext_lock(&mut);
/*
临界区
*/
fgets(linebuf,LINESIZE,fp);
fseek(fp,0,SEEK_SET);
sleep(1);
fprintf(fp,"%d\n",atoi(linebuf)+1);
fclose(fp);
pthread_mutex_unlock(&mut);
//销毁
pthread_mutex_destroy(&mut);题目:四个线程,分别输出abcd,拼命打印,公正
- thrnum 线程数量的限制
- 收尸 tid
- 创建与收尸
- 拼命打印 while
- 传递参数 i 0 1 2 3 控制所输出的character
(void *)p - 使用信号 alarm ; 5秒后被杀死
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define THRNUM 4
static void *thr_func(void *p)
{
int c='a'+(int)p;
while(1)
write(1,&c,1);//往终端打印
pthread_exit();
}
int main()
{
pthread_t tid[THRNUM];
for(i=0;i<THRNUM;i++)
{
err = pthread_create(tid+i,NULL,thr_func,(void *)i);
if(err)
{
//如果失败,报错结束
fprintf(stderr,"pthrad_create():%s\n",strerror(err));
exit(1);
}
}
alarm(5);
for(i=0;i<THRNUM;i++)
{
pthread_join(tid[i],NULL);
}
exit(0);
}- 用锁的机制,打印完a的去解锁b,让不能打印的一直阻塞在自己的锁的阶段。
- 四个互斥量。创建时初始化 并加锁.
pthread_mutex_init初始化 四次循环 初始化四把锁 第二个参数 属性 - 流程:初始化 锁上 添加线程
- 打印的函数 原来上来while 1 死循环无条件地打印。先加上自己的锁 再打印
- 在这里解下一个人 下一个锁是 mut+n+1 若为4的话 就是取0;但是不希望取模,用一个函数,
next(n) - 加锁和解锁对应的对象是一段代码 而不是变量
static pthread_mutex_t mut[THRNUM]
for(i=0 ; i<= THRNUM ; i++)
{
pthread_mutex_init(mut+i,NULL);
pthread_mutex_lock(mut+i);
err=pthread_create(tid+i,NULL,thr_func,(void *)i);
if (err)
}
pthread_mutex_unlock(mut+0);//打印a的解锁
alarm(5)
// thr_func
int n=(int)p;
int c = 'a'+n;
while(1)
{
//锁自己,解锁下一个 锁 n自己
pthread_mutex_lock(mut+n);
write(1,&c,1);
pthread_mutex_unlock(mut+next(n));
}
static int next (int n)
{
if ( n+1 == THRNUM) //也就是等于4了
return 0;
retuen n+1;
}
- 池 ,上游下发任务,把任务做成任务池,能者多劳,最大限度利用当前的资源

- 给num 做特殊值 - 当num >0 认为是待计算的任务 - 当num=0 说明无任务为空,当上游发现是0,就把下一个任务发下来。- 特殊环节,num=-1, 退出 提醒下游线程退出;上游线程等着收尸
用互斥量,加锁再枪 - 需要一个全局变量, num
- 不能用if判断,用while判断 num是否为0
#include<pthread.h>
#define LEFT 30000000
#define RIGHT 30000200
#define THRNUM 4
static int num = 0;
static pthread_mutex_t mut_num = PTHREAD_MUTEX_INITIALIZER;
static void *thr_prime(void *p);
int main()
{
int i,err;
pthread_t tid[THRNUM];
for(i=0; i <= THRNUM; i++)
{
err = pthread_create(tid+(i-LEFT),NULL,thr_prime,(void *)i);
if(err)
{
fprintf(stderr,"pthread_create():%s\n",strerr);
exit(1);
}
}
//下发任务环节
for(i = LEFT; i<= RIGHT; i++)
{
pthread_mutex_lock(&mut_num);
while(num != 0)
{
pthread_unlock(&mut_num);
sched_yield(); //出让调度器给别的线程,非常短的sleep,不会出现状态颠簸(阻塞)。短的等待
pthread_lock(&mut_num);
}
num = i;
pthread_mutex_unlock(&mut_num);
}
num=-1;
//收尸
for(i=0 ; i <= THRNUM; i++)
pthread_join(tid[i],NULL);
pthread_mutex_destroy(&mut_num);
}
static void *thr_prime(void *p)
{
int i,j,mark;
pthread_mutex_lock(&mut_num);
while(num==0)
{
pthread_
}
}
todo 只能说锁很考验了。。。
多线程令牌桶的实现 mytbf
把原来的用信号实现的改写成用多线程实现 并发版本
mytbf_mt文件夹下面;

makefile
CFLAGS+=-pthread
LDFLAGS+=-pthread
all:mytbf
mytbf:main.o mytbf.o
gcc $^ -o $@ $(CFLAGS) $(LDFLAGS)
clean:
rm -rf *.o mytbfvim * -p 打开,翻页 工具 gt 下一个标签页 pages
mytbf.h
声明
#ifndef MYTBF_H__
#define MYTBF_H__
#define MYTBF_MAX 1024
tydef void mytbf_t;
mytbf_t *mytbf_init(int cps,int burst);
int mytbf_fetchtoken(mytbf_t *,int );
int mytbf_returntoken(mytbf_t *,int );
int mytbf_destory(mytbf_t *);
#endifmytbf.c
- 完成四个函数
- 困难的地方在于 如何发出第一个alarm信号和给signal alarm信号正确的行为, init 中调用
module_load() - 希望有类似于c++构造函数使用特点出现,在init当中构造这样的内容
#include <signal.h>
#include "mytbf.h"
typedef void (*sighandler_t)(int);
static struct mytbf_st* job[MYTBF_MAX];
static int inited = 0;
static sighandler_t alrm_handler_save;
struct mytbf_st
{
int cps;
int burst;
int token;
int pos;
}- 想法是不要把过多的内容交给用户来处理