UNIX 网络编程之线程

UNIX 网络编程之线程

概述:

实现并发服务器一般都是父进程accept一个连接,然后fork一个子进程,该子进程处理与该连接对端的客户之间的通信。但是fork是昂贵,耗资源和时间。而线程是轻量级线程,它的创建比进程的创建块10-100倍。在同一进程内除了共享全局变量外还共享:

  • 大多数数据
  • 进程指令
  • 打开的文件
  • 信号处理函数信号处置
  • 当前工作目录
  • 用户ID和组ID

不过每个线程有各自的资源:

  • 线程ID
  • 寄存器集合了栈了errno
  • 信号掩码
  • 优先级

基本线程函数:创建和终止

pthread_create函数

#include <pthread.h>

int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*func)(void *), void *arg);

一个进程的每个线程都由一个线程ID标识。每个线程有很多属性,比如优先级大小,初始栈大小,是否应该成为一个守护线程等等

pthread_join函数

#include <pthread.h>

int pthread_join(pthread_t *tid, void **status);

该函数类似与waitpid

pthread_self函数

#include <pthread.h>
 int pthread_self(void);

每个线程使用pthread_self获得自身的线程ID

pthread_detach函数

#include <pthread.h>

int pthread_detach(pthread_t tid);

一个线程或者是可汇合的,或者是脱离的。当一个可汇合的线程终止时,它的线程ID和退出状态将留存到另一个线程对它调用pthread_join。脱离的线程像守护线程,当他们终止时,所有相关资源都被释放.

pthread_exit函数

#include <pthread.h>

int pthread_exit(void *status);

结束一个线程

互斥锁的使用

多线程程序的经典问题:多个线程同时修改一个共享变量(如全局变量)

#include <pthread.h>
#include <stdio.h>

int counter;
void *doit(void*);

int main(int argc, char **argv)
{
    pthread_t tidA, tidB;

    pthread_create(&tidA, NULL, &doit, NULL);
    pthread_create(&tidB, NULL, &doit, NULL);

    pthread_join(tidA, NULL);
    pthread_join(tidB, NULL);
    return 0;
}

void *doit(void * arg)
{
    int i, val;
    for(i=0; i<10; i++)
    {
        val = counter;
        printf("counter is %d\n", val+1);
        counter = val+1;
    }
    return NULL;
}

使用在对counter值进行修改之前进行上锁操作,修改之后,进行解锁操作

#include <pthread.h>
#include <stdio.h>

int counter;
pthread_mutex_t counter_mutex;

void *doit(void*);

int main(int argc, char **argv)
{
    pthread_t tidA, tidB;

    pthread_create(&tidA, NULL, &doit, NULL);
    pthread_create(&tidB, NULL, &doit, NULL);

    pthread_join(tidA, NULL);
    pthread_join(tidB, NULL);
    return 0;
}

void *doit(void * arg)
{
    int i, val;
    for(i=0; i<10; i++)
    {
        pthread_mutex_lock(&counter_mutex);
        val = counter;
        printf("counter is %d\n", val+1);
        counter = val+1;
        pthread_mutex_unlock(&counter_mutex);
    }
    return NULL;
}
<img src="https://qiniu.meowparty.cn/coder.2023/2025-01-22/Lesson-580cc07c3f06f.jpg" alt="www.zeeklog.com  - UNIX 网络编程之线程">
<img src="https://qiniu.meowparty.cn/coder.2023/2025-01-22/Lesson-f134bce722f16.jpg" alt="www.zeeklog.com  - UNIX 网络编程之线程">

Read more

决策树算法介绍:原理与案例实现

决策树算法介绍:原理与案例实现

决策树算法介绍:原理与案例实现 决策树算法介绍:原理与案例实现 一、决策树算法概述 决策树是一种基本的分类与回归方法,它基于树形结构进行决策。决策树的每一个节点都表示一个对象属性的测试,每个分支代表该属性测试的一个输出,每个叶节点则代表一个类别或值。决策树学习通常包括三个步骤:特征选择、决策树的生成和决策树的剪枝。 二、决策树算法原理 1. 特征选择 特征选择是决策树学习的核心。它决定了在树的每个节点上选择哪个属性进行测试。常用的特征选择准则有信息增益、增益比和基尼不纯度。 * 信息增益:表示划分数据集前后信息的不确定性减少的程度。选择信息增益最大的属性作为当前节点的测试属性。 * 增益比:在信息增益的基础上考虑了属性的取值数量,避免了对取值数量较多的属性的偏好。 * 基尼不纯度:在CART(分类与回归树)算法中,使用基尼不纯度作为特征选择的准则。基尼不纯度越小,表示纯度越高。 2. 决策树的生成 根据选择的特征选择准则,从根节点开始,递归地为每个节点选择最优的划分属性,并根据该属性的不同取值建立子节点。直到满足停止条件(如所有样本属于同一类,

By Ne0inhk
他给女朋友做了个树莓派复古相机,算法代码可自己编写,成本不到700元

他给女朋友做了个树莓派复古相机,算法代码可自己编写,成本不到700元

手机拍照不够爽,带个单反又太重? 试试做个树莓派复古相机,还能自己编写处理算法的那种—— 成本不到700元。 没错,颜值很高,拍出来的照片也能打: 你也可以快速上手做一个。 如何制作一个树莓派复古相机 目前,这部相机的代码、硬件清单、STL文件(用于3D打印)和电路图都已经开源。 首先是硬件部分。 这部复古相机的硬件清单如下: 树莓派Zero W(搭配microSD卡)、树莓派高清镜头模组、16mm 1000万像素长焦镜头、2.2英寸TFT显示屏、TP4056微型USB电池充电器、MT3608、2000mAh锂电池、电源开关、快门键、杜邦线、3D打印相机外壳、黑色皮革贴片(选用) 至于3D打印的相机外壳,作者已经开源了所需的STL文件,可以直接上手打印。 材料齐全后,就可以迅速上手制作了~ 内部的电路图,是这个样子的: 具体引脚如下: 搭建好后,整体电路长这样: 再加上3D外壳(喷了银色的漆)和镜头,一部简易的树莓派复古相机就做好了。 至于软件部分,

By Ne0inhk
🚀Zeek.ai一款基于 Electron 和 Vite 打造的跨平台(支持 Windows、macOS 和 Linux) AI 浏览器

🚀Zeek.ai一款基于 Electron 和 Vite 打造的跨平台(支持 Windows、macOS 和 Linux) AI 浏览器

是一款基于 Electron 和 Vite 打造的跨平台(支持 Windows、macOS 和 Linux) AI 浏览器。 集成了 SearXNG AI 搜索、开发工具集合、 市面上最流行的 AI 工具门户,以及代码编写和桌面快捷工具等功能, 通过模块化的 Monorepo 架构,提供轻量级、可扩展且高效的桌面体验, 助力 AI 驱动的日常工作流程。

By Ne0inhk