day30线程

day30-系统编程之 线程控制 sem_t sem;信号量的类型 信号量的变量。 阅读详情

1、线程概念

1、线程是轻量化的进程,一个进程内可以有多个线程,至少包含一个线程(主线程)。

2、线程的任务调度,创建,销毁的开销都要比进程小。

3、进程之间不共享资源,进程运行空间都是独立的,但是线程共享临界资源。

4、线程是任务调度的最小单位,进程是资源分配的最小单位。

5、多任务并发执行大多数选择多线程,而不是多进程,因为线程占用内存非常少大概8K。

6、多个线程每一个都有自己的id号。

7、线程函数来自于第三方库,-pthread,所以要编译线程库函数需要加上 -pthread

8、多线程编程时,对于临界资源访问时可能有多个线程同时访问,这样会产生数据的错乱,这种现象被称为竞态。

临界资源:全局变量,临界区:访问临界资源的代码。

pyhread_create

 #include <pthread.h>

       int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);
功能:创建子线程的函数
参数1:存储创建的子线程号
参数2:创建时附加的线程属性,默认填NULL
参数3:函数指针,子线程的线程体函数,也是子线程开始运行的地方。
参数4:是线程体函数的参数,如果没有参数填NULL即可。
返回值:成功返回0,失败返回-1,并且线程号不确定。
#include <myhead.h>
int k = 0;//全局变量就是临界资源
void *tang(void *n)
{
    usleep(9);
    printf("我是子线程:n = %d\n",*(int *)n);
    *(int *)n+=88;//访问全局变量的代码就叫临界区
    k = k+55;

}
int main(int argc, const char *argv[])
{
    pthread_t tid;//定义一个线程号变量
    int n=100;
    if(pthread_create(&tid,NULL,tang,&n)!=0)
    {
        perror("pthread_create");
        return -1;
    }
    usleep(90);
    printf("子线程线程号:%ld\n",tid);
    printf("主线程中k = %d\tn = %d\n",k,n);//k=55,n=188
    return 0;
}

2.线程间;数据传递

全局变量:子、主线程共享全局变量资源

#include <myhead.h>
int n = 100;
void *fun()//线程体函数
{
    sleep(1);//等待一秒
    n = n+20;
    printf("子线程中n = %d\n",n);//170
}
int main(int argc, const char *argv[])
{
    pthread_t tid;
    if(pthread_create(&tid,NULL,fun,NULL)==-1)
    {
        perror("pthread_create");
        return -1;
    }
    n = n+50;
    printf("主线程中n = %d \n",n);//150
    sleep(2);
    return 0;
}

2.局部变量作为参数地址传递,子主线程共享局部变量的资源

#include <myhead.h>
void *fun(void *n)//线程体函数
{
    sleep(1);//等待一秒
    *(int *)n+=20;
    printf("子线程中n = %d\n",*(int *)n);//170
}
int main(int argc, const char *argv[])
{
    pthread_t tid;
    int n = 100;
    if(pthread_create(&tid,NULL,fun,&n)==-1)
    {
        perror("pthread_create");
        return -1;
    }
    n = n+50;
    printf("主线程中n = %d \n",n);//150
    sleep(2);
    return 0;
}

3.结构体

#include <myhead.h>

typedef struct
{
    int id;
    char name[20];
    float score;
}stu;
void *task(void *a)//线程体函数
{
    sleep(1);
    stu *p = (stu *)a;//强制转换成具体的类型
    p->id = 1008;
}
int main(int argc, const char *argv[])
{
    pthread_t tid;
    stu a = {1001,"黑狗",98.5};
    if(pthread_create(&tid,NULL,task,&a)==-1)
    {
        perror("pthread_create");
        return -1;
    }
    sleep(2);
    printf("主线程中学号:%d\n",a.id);
    return 0;
}

pthread_self获取线程号

#include <pthread.h>

       pthread_t pthread_self(void);
        功能:获取调用线程的线程号
        参数:无
        返回值:返回调用线程的线程号。
#include <myhead.h>

void *task(void *a)//线程体函数
{
    printf("子线程中自己的ID  =%ld\n",pthread_self());//输出调用线程自己的ID
}
int main(int argc, const char *argv[])
{
    pthread_t tid;
    if(pthread_create(&tid,NULL,task,NULL)==-1)
    {
        perror("pthread_create");
        return -1;
    }
    sleep(2);
    printf("主线程中子线的ID = %ld\n",tid);
//输出子线程的ID
    printf("主线程中自己的ID = %ld\n",pthread_self());//主线程获取自己的ID
    return 0;
}

pthread_exit线程退出

#include <pthread.h>

       void pthread_exit(void *retval);
        功能:退出调用线程
        参数:任意类型的变量,存储检索后的内容。
        返回值:无

#include <myhead.h>

void *task(void *a)//线程体函数
{
    sleep(1);
    printf("子线程中自己的ID  =%ld\n",pthread_self());
    pthread_exit(NULL);//线程退出函数
    //exit(0);//整个进程退出
    while(1);
}
int main(int argc, const char *argv[])
{
    pthread_t tid;
    if(pthread_create(&tid,NULL,task,NULL)==-1)
    {
        perror("pthread_create");
        return -1;
    }
    sleep(2);
    printf("主线程中子线的ID = %ld\n",tid);
    printf("主线程中自己的ID = %ld\n",pthread_self());
    while(1);
    return 0;
}

6、pthread_join/pthread_detach线程回收和挂起

#include <pthread.h>

       int pthread_join(pthread_t thread, void **retval);
        功能:阻塞回收子线程的资源。
        参数1:要退出的线程号
        参数2:线程退出时的状态,一般不接收填NULL。
        返回值:成功返回0,失败返回一个错误码。
        
        #include <pthread.h>

       int pthread_detach(pthread_t thread);
        功能:非阻塞将线程设置为分离态,设置为分离态的线程由系统回收资源。
        参数:要设置为分离态的线程号
        返回值:成功返回0,失败返回一个错误码。
        
#include <myhead.h>

void *task(void *a)//线程体函数
{
    sleep(5);
    printf("子线程中自己的ID  =%ld\n",pthread_self());
    pthread_exit(NULL);//线程退出函数
}
int main(int argc, const char *argv[])
{
    pthread_t tid;
    if(pthread_create(&tid,NULL,task,NULL)==-1)
    {
        perror("pthread_create");
        return -1;
    }
    
    //pthread_join(tid,NULL);//主线程阻塞回收子线程的资源
    pthread_detach(tid);//非阻塞将子线程设置为分离态

    //printf("子线程资源已经被回收\n");
    printf("子线程成功设置为分离态\n");
    return 0;
}

验证设置为分离态的子线程是否共享主线程资源:依然共享资源。

#include <myhead.h>
//现将子线程设置为分离态,验证设置为分离态的子线程是否共享主线程资源
int n = 100;
void *task(void *a)//线程体函数
{
    sleep(2);
    printf("n = %d\n",n);
    while(1);
}
int main(int argc, const char *argv[])
{
    pthread_t tid;
    if(pthread_create(&tid,NULL,task,NULL)==-1)
    {
        perror("pthread_create");
        return -1;
    }
    pthread_detach(tid);//设置子线程为分离态 
    n = n+50;    
    while(1);    
    return 0;
}

 验证子线程退出后,子线程是否会立即退出:不会立即退出。子线程依赖主进程

#include <myhead.h>
void *task(void *a)//线程体函数
{
    while(1)
    {
        printf("我还活着\n");
        sleep(1);
    }
    while(1);
}
int main(int argc, const char *argv[])
{
    pthread_t tid;
    if(pthread_create(&tid,NULL,task,NULL)==-1)
    {
        perror("pthread_create");
        return -1;
    }
    //pthread_detach(tid);//设置子线程为分离态 
:    
    pthread_exit(NULL);//主线程退出
    while(1);
    return 0;
}

作业:多线程实现文件拷贝,线程拷贝一半,线程拷贝另一半,主线程回收子线程资源。

#include <luochen.h>
//1、计算出文件1的大小,创建文件2
//2、创建两个线程函数
//3、将文件名,拷贝的起始位置和拷贝长度传递给线程函数
//4、线程函数调用拷贝函数实现拷贝
typedef struct
{
    const char *src;//源文件
    const char *des;//目标文件
    int start;//拷贝的起始位置
    int len;//拷贝的长度
}file_st;

int file_length(const char *p1,const char *p2)
{
    int fd1 = open(p1,O_RDONLY);//只读方式打开文件1
    if(fd1==-1)
    {
        perror("open");
        return -1;
    }
    int len = lseek(fd1,0,SEEK_END);
    int fd2 = open(p2,O_CREAT|O_TRUNC|O_WRONLY,0664);
    if(fd2==-1)
    {
        perror("open");
        return -1;
    }
    close(fd1);
    close(fd2);
    return len;//返回文件1的大小

}
int copy_file(const char *p1,const char *p2,int start,int len)
{
    int fd1,fd2;
    if((fd1 = open(p1,O_RDONLY))==-1)
    {
        perror("open");
        return -1;
    }
    if((fd2 = open(p2,O_WRONLY))==-1)
    {
        perror("open");
        return -1;
    }
    lseek(fd1,start,SEEK_SET);
    lseek(fd2,start,SEEK_SET);
    int sum=0;
    char buff[100];
    while(1)
    {
        int res = read(fd1,buff,sizeof(buff));
        sum+=res;
        if(res==0||sum>=len)
        {
            write(fd2,buff,res-(sum-len));
            break;
        }
        write(fd2,buff,res);
    }
    close(fd1);
    close(fd2);
    return 0;
}

void *fun1(void *p)
{
    file_st *fi = (file_st *)p;
    copy_file(fi->src,fi->des,fi->start,fi->len);//调用拷贝函数
}
void *fun2(void *p)
{
    file_st *fi = (file_st *)p;
    copy_file(fi->src,fi->des,fi->start,fi->len);//调用拷贝函数
}
int main(int argc, const char *argv[])
{
    if(argc!=3)
    {
        printf("外部传参错误\n");
        return -1;
    }

    int len = file_length(argv[1],argv[2]);//算出文件1的大小,创建文件2

    file_st a = {argv[1],argv[2],0,len/2};
    file_st b = {argv[1],argv[2],len/2,len-len/2};

    pthread_t tid1,tid2;
    if(pthread_create(&tid1,NULL,fun1,&a)==-1)//调用子线程1拷贝文件
    {
        perror("pthread_create");
        return -1;
    }
    if(pthread_create(&tid2,NULL,fun2,&b)==-1)//调用子线程2拷贝文件
    {
        perror("pthread_create");
        return -1;
    }
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);//阻塞回收子线程的资源
    
    return 0;
}

瑞芯微RK3506开发板DSM音频开发避坑指南:从硬件改接到内核配置全流程 本文详细解析了在瑞芯微RK3506开发板上进行DSM音频开发的完整流程与关键避坑点。内容涵盖从硬件改造(如电阻焊接)、内核驱动配置(DTS参数、补丁应用)到系统调试与波形分析的全过程,旨在帮助嵌入式开发者高效实现高信噪比、低成本的音频方案,避免常见错误。 阅读详情

相关推荐

[WeChatMsg]导出csv格式微信聊天记录的手把手教程

手把手教大家如何导出自己的聊天记录得到csv文件,即使是电脑小白也可以轻松学会o(* ̄▽ ̄*)ブ

weixin_51094633的博客 1万+

Day30 线程安全

1.评讲作业2.买票的案例 – 线程安全 (重要)1.完全掌握卖票案例2.理解对象内存结构 - https://blog.youkuaiyun.com/weixin_44606481/article/details/1348024193.线程安全 — 买票案例synchronized代码块synchronized方法(成员同步方法、静态同步方法)Lock锁注意:1.加锁的方式2.锁对象(多个线程去操作同一把锁才能互斥住)

weixin_69595694的博客 1151

STC8H DMA 串口1全双工中断方式收发通讯C语言

串口1全双工中断方式收发通讯程序。 通过PC向MCU发送数据, MCU将收到的数据自动存入DMA空间. 当DMA空间存满设置大小的内容后,通过串口1的DMA自动发送功能把存储空间的数据原样返回. 用定时器做波特率发生器,建议使用1T模式(除非低波特率用12T),并选择可被波特率整除的时钟频率,以提高精度。

czhaii的专栏 1466

day 30 线程创建回收,线程属性,指针函数

线程是轻量级的进程定义:正在执行的程序;进程是操作系统资源分配的最小单位;线程是轻量级进程。线程一定属于进程。与同一进程中的其他线程共用进程的堆区,数据区,文本区线程是cpu任务调度的最小单位。资源消耗:进程消耗的资源空间大消耗的资源空间小,只需分配栈区效率角度:创建线程比创建进程效率高任务切换跨进程效率低于跨线程安全角度:由于进程空间独立,所以安全性比线程高。通信角度:进程间不能直接通信,需要使用进程间通信方式(IPC)实现。

qq_53671628的博客 709

命令行删除描述文件_写一个删除lock文件的skill脚本

来源:IC技能搬运工 作者:小目Cadence软件使用过程中偶尔会遇到文件被lock的情况,这是Cadence软件对文件的一种保护措施,大部分情况都是对用户友好的,但是偶尔也会给用户带来困扰,给工作带来的一定的不便。文件是如何被锁的Cadence在用户打开文件进行编辑的时候会在文件的同一级目录新建一个lock文件,用来标识文件的状态。一般情况下如果文件被正常关闭,这个lock文件会在...

weixin_39781452的博客 1352

SAP物料分类账(ML)避坑指南:激活顺序错了怎么办?从CKMSTART到差异分摊的完整流程

本文详细解析SAP物料分类账(ML)的正确激活顺序与配置流程,帮助用户避免常见陷阱如'LKW无科目'、'在制品重估失败'等问题。从CKMSTART到差异分摊的完整流程,涵盖关键配置节点、典型报错分析与应急处理方案,确保产品成本控制(CO-PC)模块的顺利运行。

weixin_42524708的博客 258

Day 30 学习分享 - 线程

1. 线程安全 1.1 线程安全概述 如果有多个线程在同时运行, 这些线程有可能会同时运行一段代码, 程序每次运行结果和单线程运行的结果是一样的, 而且其他的变量的值也和预期相同, 这就是一个安全的线程. 1.2 案例演示 public class Ticket implements Runnable { // 共100票 int ticket = 100; @Override public void run() { while (ticket > 0) { // 同步代码块

WrathPudge的博客 174

unity制作交互视频/互动视频

unity制作交互视频/互动视频 思路 1.先让unity播放视频 2. 视频播放结束后,视频暂停,按钮出现 3.按钮跳转下一个视频 视频播放 先创建UI-Raw Iamge 在Raw Iamge 挂载组件 Video Player 接着挂载视频播放的脚本 using UnityEngine; using UnityEngine.UI; using UnityEngine.Video; publi...

weixin_45588911的博客 8423

I\O进程线程(Day30)

使用 `pthread_create` 创建线程,`pthread_self` 获取线程号,`pthread_exit` 退出线程,`pthread_join` 回收线程资源,`pthread_detach` 实现非阻塞线程分离。

weixin_65095004的博客 1403

Python爬虫实战:5分钟搞定东方财富网股票数据抓取(附完整代码)

本文详细介绍了如何利用Python爬虫技术,快速抓取东方财富网的实时股票数据。通过逆向分析其JSONP数据接口,构建了包含请求处理、数据清洗、分页调度及多格式存储的完整自动化采集系统,并提供了应对反爬策略与生产部署的进阶优化思路,附有可直接运行的完整代码。

weixin_29084231的博客 875

IEC61850规约客户端软件开发实战(第二章)

本文介绍了基于IEC61850规约的客户端软件开发过程,重点阐述功能界面设计和服务端连接功能的实现。界面采用Qt框架设计,包含功能按钮区、数据模型展示区(使用QTreeWidget)和状态显示区。连接功能通过libiec61850开源库实现,详细说明了连接流程、句柄创建及状态管理的代码实现。测试结果表明系统能正确识别连接状态,并通过界面直观显示。文章为IEC61850规约软件开发提供了实用参考,下期将分享规约模型数据加载的实现过程。

半青年的博客 2856

Java高级Day30-线程补充

/主线程每隔1s,输出hi,一共10次,当输出到第5次,启动一个子线程,每隔1s输出hello,等该线程输出10次hello后,退出,主线程继续输出hi,直到主线程退出。也可以这样理解:线程同步,即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作。线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁。守护线程:一般是为工作现场服务的,当所有的用户线程结束,守护线程自动结束。

2301_78630849的博客 394

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

day30:多线程

多线程的概念、线程的创建(pthread_create)、共享进程资源、线程号的获取(pthread_self)、线程退出函数(pthread_exit)、线程的资源回收(pthread_join)、向线程发信号(pthread_cancel)、线程分离(pthread_detach)

wxmchong的博客 81

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Java-day30-多线程02

当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢?Java中的线程状态被定义在了java.lang.Thread.State枚举类中,State枚举类的源码如下: 通过源码我们可以看到Java中的线程存在6种状态,每种线程状态的含义如下各个状态的转换,如下图所示:概述 :​ 提到池,大家应该能想到的就是水池。水池就是一个容器,在该容器中存储了很多的水。那么什么是线程池呢?线程池也是可以看做成一个池子,在

m0_73766712的博客 793

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Java-day30-多线程额外扩展

提到池,大家应该能想到的就是水池。水池就是一个容器,在该容器中存储了很多的水。那么什么是线程池呢?线程池也是可以看做成一个池子,在该池子中存储很多个线程。线程池存在的意义:系统创建一个线程的成本是比较高的,因为它涉及到与操作系统交互,当程序中需要创建大量生存期很短暂的线程时,频繁的创建和销毁线程对系统的资源消耗有可能大于业务处理是对系统资源的消耗,这样就有点"舍本逐末"了。针对这一种情况,为了提高性能,我们就可以采用线程池。线程池在启动的时,会创建大量空闲线程,当我们向线程池提交任务的时,线程池就。

m0_73766712的博客 894

day30-进程和线程(3)

●只能加锁一次,加锁期间不能再次加锁,也不能强制占有一个已经加锁的锁资源,必须等待锁资源释放,也就是解锁后才能继续操作该锁。●如果信号量资源数为0,申请资源会阻塞等待,直到占用资源的任务释放资源,资源数不为0时才能申请到资源并继续向下执行。●一个进程中的多个线程独享栈空间,文本段、数据段、堆区进程多线程共享。●只能防止多个线程对资源的竞争,不能决定代码的先后执行顺序。,则会阻塞等待,直到有任务释放资源,才能拿到资源并继续向下执行。●信号量只能完成四种操作(初始化,销毁,申请,释放)

m0_75094223的博客 897

【新手向】从零开始学习Java(Day30)Java 多线程

一起从零开始成就Java大神!

黎明前的黑暗最为深邃,但只要你坚持,曙光终会划破天际。 827

Day26 3.30 IO进程线程

IO函数 线程

kcncoooo的博客 172

Day29-30.线程安全、线程同步synchronized() 、死锁

JavaSE 多线程

a111042555的博客 1031

day30——零基础学嵌入式之线程2.0

信号量类型 信号量的变量。

sx243694的博客 1136

Day30 多线程编程 同步与互斥 任务队列调度

主线程负责初始化数据结构和创建线程,工作线程执行具体计算任务。主线程负责回收线程资源并汇总显示结果。注:实际输出顺序和线程ID会因随机数和系统调度而不同,但会包含10组线程输出,最后显示主线程退出信息。

oareen的博客 982

day30 网络编程 之进程,线程,协程

进程点进去 线程点进去 协程点进去 什么是进程  进程(有时称为重量级进程)是一个执行中的程序。每个进程都拥有自己的地址空间、内存、数据栈以及其他用于跟踪执行的辅助数据。同一个程序执行两次,属于是两个不同进程。 什么是线程 线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。与同属一个进程的其它线程共享进程所拥有的...

weixin_30826761的博客 138

Python开发基础-Day30多线程锁机制

GIL(全局解释器锁) GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念,是为了实现不同线程对共享资源访问的互斥,才引入了GIL 在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势 python对于计算密集型的任务开多线程的效率甚至不如串行(没有大量切换),但是,对于IO密集型的任务效...

dichu0602的博客 152

Day30.守护线程、定时器、线程通信| 消费者模式 | wait、notify方法

JavaSE 线程安全

a111042555的博客 2952

Day30 线程安全之窗口售票问题(含代码)

本节主要讲解线程安全里极为重要的窗口售票问题,深度刨析帮助理解线程安全。

yjp1240201821的博客 722

嵌入式学习笔记DAY30(线程的控制:互斥和同步)

semaphore。

m0_67864116的博客 752
上一篇: 多线程并发
下一篇: day 多点通信
luochen330x
博客等级 码龄2年 294粉丝 48原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值