网页视频制作软件整站外包优化公司
Linux系统线程
- 多进程实现并发
CPU时分复用,单核心CPU可以实现宏观上的并行,以满足多任务需求。
但是,进程间切换开销大,进程间通信麻烦而且效率低。
解决方案就是线程技术,线程技术保留了进程技术实现多任务的特性。线程的改进就是在线程间切换和线程间通信上提升了效率,并且多线程在多核心CPU上面更有优势。
int ret = -1;ret = fork();if (ret == 0){// 子进程(阻塞式)}else if (ret > 0){// 父进程(阻塞式)}else {perror();}
- 多线程
线程像进程一样可以被OS单独调度,同一个进程的多个线程之间很容易高效率通信。在多核心CPU(对称多处理器架构SMP)架构下效率最大化。
pthread_create()
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>void *func(void *arg)
{char buf[200];//线程函数while(1){memset(buf, 0, sizeof(buf));printf("before read.\n");read(0, buf, 5);printf("读出的键盘内容是: [%s].\n", buf);}
}int main(void)
{//创建子进程,父子进程分别进程读键盘和鼠标的工作int ret = -1,fd = -1;char buf[200];pthread_t th = -1;//创建线程ret = pthread_create(&th, NULL, func, NULL);if(ret != 0){printf("pthread_create error!.\n");return -1;}//主任务fd = open("/dev/input/mouse0", O_RDONLY);if(fd < 0){perror("open");return -1;}while(1){memset(buf, 0, sizeof(buf));printf("before read.\n");read(fd, buf, 50);printf("读出的鼠标内容是: [%s].\n", buf);}return 0;
}
编译命令:gcc 3.7.2.c -lpthread // -l链接函数库
- 线程的创建与回收
pthread_create 主线程用来创造子线程
pthread_join 主线程用来等待(阻塞)回收子进程
pthread_detach 主线程用来分离子线程,分离后主线程不必再回收子线程- 线程取消
pthread_cancel 一般都是主线程调用该函数去取消子线程
pthread_setcancelstate 子进程设置自己是否允许被取消
pthread_setcanceltype- 线程函数退出机制
pthread_exit与return退出
pthread_cleanup_push
pthread_cleanup_pop- 获取线程id
pthread_self
- 线程同步
- 信号量(sem)
用户从终端输入任意字符然后统计个数显示,输入end则结束
使用多线程实现:主线程获取用户输入并判断是否退出,子线程计数
线程的同步问题:子线程被阻塞,主线程可以激活
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>char buf[200]={0};
sem_t sem;
//子线程程序,计数
void *func(void *arg)
{//子线程首先应该有个循环//循环总阻塞等待主线程激活,激活后获取buf长度,完成后再次阻塞sem_wait(&sem);while(strncmp(buf, "end", 3)){printf("输入了%ld个字符。\n", strlen(buf));memset(buf, 0, sizeof(buf));sem_wait(&sem);}pthread_exit(NULL);
}int main(void)
{pthread_t th = -1,ret = -1;sem_init(&sem, 0, 0);//信号量初始化零ret = pthread_create(&th, NULL, func, NULL);if(ret != 0){printf("pthread_create error.\n");return 0;}printf("输入一个字符串(以回车结束)。\n");while(scanf("%s", buf)){if(!strncmp(buf, "end", 3)){printf("程序结束\n");sem_post(&sem);break;}//主线程收到用户字符串,确定不是end后发信号激活子线程sem_post(&sem);}//回收子线程printf("等待回收子线程\n");ret = pthread_join(th, NULL);if(ret != 0){printf("pthread_join error.\n");return 0;}printf("子线程回收成功\n");sem_destroy(&sem);return 0;
}
- 互斥锁(mutex)
相关函数:pthread_mutex_init pthread_mutex_destroy pthread_mutex_lock pthread_mutex_unlock
互斥锁和信号量的关系:互斥锁是一种特殊的信号量,只有0和1的信号量;互斥锁主要用来实现关键段保护。
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>char buf[200]={0};
pthread_mutex_t mutex;
int flag = 0;
//子线程程序,计数
void *func(void *arg)
{sleep(1);while(flag == 0){pthread_mutex_lock(&mutex);sleep(0.5);printf("输入了%ld个字符。\n", strlen(buf));memset(buf, 0, sizeof(buf));pthread_mutex_unlock(&mutex);sleep(1);}pthread_exit(NULL);
}int main(void)
{pthread_t th = -1,ret = -1;pthread_mutex_init(&mutex, NULL);ret = pthread_create(&th, NULL, func, NULL);if(ret != 0){printf("pthread_create error.\n");return 0;}printf("输入一个字符串(以回车结束)。\n");while(1){//上锁与解锁pthread_mutex_lock(&mutex);scanf("%s", buf);pthread_mutex_unlock(&mutex);if(!strncmp(buf, "end", 3)){printf("程序结束\n");flag = 1;break;}sleep(1);}//回收子线程printf("等待回收子线程\n");ret = pthread_join(th, NULL);if(ret != 0){printf("pthread_join error.\n");return 0;}printf("子线程回收成功\n");pthread_mutex_destroy(&mutex);return 0;
}
- 条件变量
条件变量通常与互斥锁(mutex)一起使用,以确保在等待条件变量时不会发生竞态条件。条件变量允许一个或多个线程等待某个条件的发生,而其他线程可以在条件发生时通知等待的线程。
相关函数:
pthread_cond_init pthread_cond_destroy
pthread_cond_wait pthread_cond_signal / pthread_cond_broadcast
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>char buf[200]={0};
pthread_mutex_t mutex;
int flag = 0;
pthread_cond_t conde;///
//子线程程序,计数
void *func(void *arg)
{while(flag == 0){pthread_mutex_lock(&mutex);pthread_cond_wait(&conde, &mutex);///printf("输入了%ld个字符。\n", strlen(buf));memset(buf, 0, sizeof(buf));pthread_mutex_unlock(&mutex);}pthread_exit(NULL);
}int main(void)
{pthread_t th = -1,ret = -1;pthread_mutex_init(&mutex, NULL);pthread_cond_init(&conde, NULL);ret = pthread_create(&th, NULL, func, NULL);if(ret != 0){printf("pthread_create error.\n");return 0;}printf("输入一个字符串(以回车结束)。\n");while(1){scanf("%s", buf);pthread_cond_signal(&conde);///if(!strncmp(buf, "end", 3)){printf("程序结束\n");flag = 1;break;}}//回收子线程printf("等待回收子线程\n");ret = pthread_join(th, NULL);if(ret != 0){printf("pthread_join error.\n");return 0;}printf("子线程回收成功\n");pthread_mutex_destroy(&mutex);pthread_cond_destroy(&conde);return 0;
}