死在山野的风里,活在自由的梦里
本专栏参考教材是四川轻化工大学陈年老师的linux实验指导手册(含学习通的一些程序笔记)。
POSIX线程编程
- 1.线程是什么
- 2.创建线程
- 创建一个用户级的线程,实现在线程中更改进程(主线程)中的数据并输出验证修改结果。26-2.c
- 利用多线程实现单词统计,即通过命令行参数指定多个文件给程序统计其中的单词数,程序采用为每一个文件创建一个线程来统计其单词数。
1.线程是什么
是一个程序内可被操作系统调用的,可以并发运行的任务
用于同时监控一个程序里面的多个并发的任务
(如果用父子进程也能同时监控,但是是用不同进程去监控的)
切换时开销更小
2.创建线程
创建一个用户级的线程,实现在线程中更改进程(主线程)中的数据并输出验证修改结果。26-2.c
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>
static int i = 1;
//i是全局变量
void *create(void *arg)
{ //函数名前加*,说明返回的是一个指向函数的指针
printf("new pthread ...\n");
printf("shared data = %d\n",i);
printf("my tid is %ld\n",(unsigned long int)pthread_self());
//在线程中通过pthread_self()函数返回自己的pid,类型为无符号长整数(unsigned long int),在printf中用%ld格式化输出。
i=2;
//修改全局变量i的值
return (void *)0;
}
int main()
{
pthread_t l;
//l用来存储线程的tid,数据类型pthread_t是无符号长整数(unsigned long int)
i=3;
//修改全局变量i的值
if(pthread_create(&l,NULL,create,NULL))
{ //pthread_create()函数需要四个参数,其中第一个是存线程tid的地址&l,并且会向l返回所创建线程的tid,第三个变量是线程程序的起始地址,即指向线程程序的指针
//pthread_create()函数成功则返回0,否则返回出错编号
printf("create pthread failed\n");
return -1;
}
else
{
sleep(1);
printf("create pthread successfully\n");
printf("And shared data = %d\n return tid = %ld\n",i,(unsigned long int)l);
//输出main中i的值以及pthread_create()函数所创建线程的ID——l的值
return 0;
}
int n = sizeof(pthread_t);
printf("the pthread_t has %d Byte\n",n);
}
完成利用多线程实现单词统计的实验(参考教科书P264例子)。
利用多线程实现单词统计,即通过命令行参数指定多个文件给程序统计其中的单词数,程序采用为每一个文件创建一个线程来统计其单词数。
提示:可以包含ctype.h文件,利用isalnum(int c)函数判断字符变量c是否为数字或字母,是则返回真(非零)。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
int aaa(char filename[256])
{
char ch;
int wordStart = 0, sum = 0; // sum单词总数
int i = 0, j = 0;
char copy[20] = ""; //暂存读取的一个完整单词
FILE *fp = NULL;
fp = fopen(filename, "r");
if (fp == NULL)
{
printf("文件打开出错了!");
exit(0);
}
//读取文件内容
while (!feof(fp))
{
ch = fgetc(fp);
if (isalpha(ch)) //单词开始
{
wordStart = 1; //标记
copy[i++] = ch; //把一个完整单词每个字符依次存进copy
}
else if (!isalpha(ch) && wordStart == 1) //判断一个单词结束
{
sum++; //单词总个数+1
//必须要这两个,不然会把别的字符也当成单词
wordStart = 0;
i = 0;
for (j = 0; j < 20; j++) //一个单词结束,copy清空
{
fflush(stdout);
}
}
}
printf("%s 总单词数为 %d \n", filename, sum);
return sum;
}
int count[30] = {0}; //文件单词数初始值都是0
pthread_mutex_t fileMutex; //定义一个互斥变量
int main(int argc, char **argv)
{
int i = 0;
int flag; //如果输入命令格式不正确,应该给出提示
if (argc < 2)
{
printf("./xx 1.txt 2.txt");
exit(0);
}
*argv++; // +1
pthread_t thread[argc - 1];
/*互斥锁初始化*/
flag = pthread_mutex_init(&fileMutex, NULL);
if (flag != 0)
{
perror("出错了\n");
return 1;
}
for (i = 0; i < argc - 1; i++)
{
flag = pthread_create(&thread[i], NULL, (void *)aaa, *argv++);
if (flag != 0)
return 1;
}
for (i = 0; i < argc - 1; i++)
pthread_join(thread[i], (void **)&count[i]);
int sum = 0;
for (i = 0; i < 30; i++)
sum += count[i];
printf("总单词数量 %d", sum);
return 0;
}