当前位置: 首页 > news >正文

Linux系统线程

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

相关文章:

  • es中节点类型有哪些
  • npm 项目命名规则
  • innodb如何实现mvcc的
  • 【JS】使用滑动窗口得到无重复字符的最长子串
  • Linux系统高级IO
  • 还是主题混合程序设计
  • Redash:一个开源的数据查询与可视化工具
  • 如何查看 MySQL 的磁盘空间使用情况:从表级到数据库级的分析
  • YOLOv12 训练从这里开始:LabelImg 标注数据集
  • 详解 MySQL 索引的最左前缀匹配原则
  • 【C语言】内存函数
  • SQLark(百灵连接):一款面向信创应用开发者的数据库开发和管理工具
  • 一周学会Pandas2 Python数据处理与分析-NumPy数组创建
  • 网络建设与运维神州数码DCN 基于流的重定向
  • LVGL修改标签文本,GUI Guider的ui不生效
  • 实验研究:不同物体与落点材质对弹起高度的影响
  • app逆向专题一:如何下载app
  • 【C++】多线程编程大礼包
  • Java 责任链模式 详解
  • 初阶数据结构--树