首页 > 其他分享 >线程复习

线程复习

时间:2023-06-22 11:11:08浏览次数:41  
标签:复习 int mutex pthread 线程 sem NULL

2023/6/22 线程的使用,基础知识,总结复习,后续慢慢补充

特点

  1. Linux同样用task_struct来描述一个线程,线程和进程都参与统一调度
  2. 线程共享该进程的地址空间
  3. 线程是系统调度的最小单位,进程是资源分配的最小单位。
  4. 线程通信简单,全局变量可以实现,但是需要考虑临界资源保护问题

基础函数接口

1、 int pthread_create(pthread_t *thread, const pthread_attr_t *attr, 
                    void *(*start_routine) (void *), void *arg);
2、int  pthread_exit(void *value_ptr) //结束线程
3、int  pthread_join(pthread_t thread,  void **value_ptr) //回收线程
  //阻塞函数,等待一个指定的线程结束  value_ptr:指针*value_ptr指向线程返回的参数
4、pthread_t pthread_self(void); //获取线程号
5、int pthread_detach(pthread_t thread); //让线程分离,线程退出让系统自动回收线程资源

线程的补充函数接口

线程同步

通过信号量实现线程同步,同步就是多个任务(线程)按照约定的顺序相互配合完成一件事。这里面涉及了PV操作 P操作当信号量的值大于0时,可以申请资源,申请后,信号量减少1,如果为0就没法执行P操作,这时会阻塞V操作不阻塞,信号量增加1

1、//初始化信号量
    int  sem_init(sem_t *sem,  int pshared,  unsigned int value) //sem信号量对象,int 0为线程,1为进程间可以使用
    int  sem_wait(sem_t *sem) //申请资源,P操作
    int  sem_post(sem_t *sem) //释放资源 V操作

线程互斥

作用:多个线程访问临界资源时,使一次仅允许一个线程使用资源。
加入互斥锁实现功能,每个临界资源都由一个互斥锁来保护,线程必须要线获得互斥锁才能访问临界资源,访问资源后释放该锁。如果无法获得锁,线程会阻塞直到获得锁为止。
补充概念:死锁是指两个或两个以上的进程/线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去
死锁产生的四个必要条件
1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
注意:当上述四个条件都成立的时候,便形成死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失。

1、int  pthread_mutex_init(pthread_mutex_t  *mutex, pthread_mutexattr_t *attr)  //atter为NULL为缺省
2、int  pthread_mutex_lock(pthread_mutex_t *mutex)  //申请互斥锁 阻塞
3、int  pthread_mutex_trylock(pthread_mutex_t *mutex)  //申请互斥锁,非阻塞
4、int  pthread_mutex_unlock(pthread_mutex_t *mutex)  //释放互斥锁
5、int  pthread_mutex_destroy(pthread_mutex_t  *mutex) //销毁互斥锁

功能代码

线程的创建与回收

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


char buf[32] = "";
//线程函数
void *handler(void *arg)
{
    sleep(1);
    printf("in the thread\n");
    printf("num:%d\n", *((int *)arg));
    printf("buf:%s\n", buf);
    pthread_exit(NULL); //结束线程
}
int main(int argc, char const *argv[])
{
    pthread_t tid;
    int num = 100;//给线程传值的
    if(pthread_create(&tid, NULL, handler, &num) != 0)
    {
        perror("create thread err");
        return -1;
    }
    printf("in the main\n");
    printf("main tid:%lu\n", pthread_self());
    strcpy(buf, "hello");//全局变量直接通信
    //线程回收,阻塞函数,等待子线程结束,回收线程资源
    pthread_join(tid, NULL);

    return 0;
}

根据标志位读输入打印输出

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

char buf[32]="";
int local=0;
int main()
{
    pthread_t  tid;
    if(pthread_create(&tid,NULL,add,NULL)!=0)
    {
        perror("per");
        return -1;
    }
    while(1)
    {
        if(local==0)
        {
            fgets(buf,32,stdin);
            local=1;
            if(strcmp(buf,"quit")==0)
            {
                break;
            }
        }
    }
    pthread_join(tid,NULL);
}
void *add(void *a)
{
    while(1)
    {
        if(local==1)
        {
            if(strcmp(buf,"quit")==0)
            {
                break;
            }
            printf("%s\n",buf);
            local=0;
            memset(buf,0,32);
        }
    }
}

线程同步2个信号量的PV操作

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


char buf[32] = "";
sem_t sem, sem1;
void *print(void *arg)
{
    while (1)
    {
        //P操作:申请资源,-1
        sem_wait(&sem);
        if (strcmp(buf, "quit") == 0)
            break;
        printf("buf:%s\n", buf);
        sem_post(&sem1);
    }
}
int main(int argc, char const *argv[])
{
    pthread_t tid;
    if (pthread_create(&tid, NULL, print, NULL) != 0)
    {
        perror("create thread err");
        return -1;
    }
    if(sem_init(&sem, 0, 0) < 0)
    {
        perror("sem init err");
        return -1;
    }
    if(sem_init(&sem1, 0, 1) < 0)
    {
        perror("sem init err");
        return -1;
    }
    while (1)
    {
        //申请
        sem_wait(&sem1);
        printf("请输入:");
        scanf("%s", buf);
        //V操作:释放资源, +1
        sem_post(&sem);
        if (strcmp(buf, "quit") == 0)
            break;
    }
    pthread_join(tid, NULL);


    return 0;
}

使用互斥锁打印数组中元素

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


int a[10] = {0,1,2,3,4,5,6,7,8,9};
pthread_mutex_t lock;
void *print_handler(void *arg)
{
    while(1)
    {
        pthread_mutex_lock(&lock);
        for(int i = 0; i < 10; i++)
            printf("%d", a[i]);
        printf("\n");
        pthread_mutex_unlock(&lock);
        sleep(1);
    }
}
void *swap_handler(void *arg)
{
    int t;
    while(1)
    {
        pthread_mutex_lock(&lock);
        for(int i = 0; i < 5; i++)
        {
            t = a[i];
            a[i] = a[9-i];
            a[9-i] = t;
        }
        pthread_mutex_unlock(&lock);
    }
}
int main(int argc, char const *argv[])
{
    pthread_t t1, t2;
    pthread_create(&t1, NULL, print_handler, NULL);
    pthread_create(&t2, NULL, swap_handler, NULL);


    if(pthread_mutex_init(&lock, NULL) != 0)
    {
        perror("mutex init err");
        return -1;
    }


    pthread_join(t1, NULL);
    pthread_join(t2, NULL);


    return 0;
}

标签:复习,int,mutex,pthread,线程,sem,NULL
From: https://www.cnblogs.com/moveddown/p/17497596.html

相关文章

  • 字节二面:如何应对Framework层中多进程和线程通信场景
    如果有人问:“在当下环境中,什么样的安卓程序员,不容易被淘汰?”我的答案是:“底层开发!”互联网行业,更新迭代非常快,目前Android底层的架构也在不断调整和优化中,这说明目前的不是最优解,而Android更新迭代了这么多版本,需要兼容旧版本,有些地方不能完全放开去设计,需要在兼容和完全优化中做选......
  • Java—多线程
    ......
  • java中synchronized和ReentrantLock的加锁和解锁能在不同线程吗?如果能,如何实现?
    java中synchronized和ReentrantLock的加锁和解锁能在不同线程吗?如果能,如何实现?答案2023-06-21:java的:这个问题,我问了一些人,部分人是回答得有问题的。synchronized这是个关键字,加锁和解锁不是直接用代码实现,所以在代码层面上就杜绝了加锁和解锁不在同一个线程得情况。可以这么说,synch......
  • java中synchronized和ReentrantLock的加锁和解锁能在不同线程吗?如果能,如何实现?
    java中synchronized和ReentrantLock的加锁和解锁能在不同线程吗?如果能,如何实现?答案2023-06-21:java的:这个问题,我问了一些人,部分人是回答得有问题的。synchronized这是个关键字,加锁和解锁不是直接用代码实现,所以在代码层面上就杜绝了加锁和解锁不在同一个线程得情况。可以这么说,s......
  • 并行计算中的线程和进程:原理与实践
    目录1.引言2.技术原理及概念2.1基本概念解释2.2技术原理介绍3.实现步骤与流程3.1准备工作:环境配置与依赖安装3.2核心模块实现3.3集成与测试4.应用示例与代码实现讲解4.1应用场景介绍4.2应用实例分析4.3核心代码实现4.4代码讲解说明5.优化与改进5.1性能优化并行计算......
  • springboot 默认配置的线程池
     线程池的大小通常都是我们比较关注的,SpringBoot会为系统做默认配置。如果不清楚SpringBoot默认配置的线程池的大小的话,容易线上踩坑。最近碰到一个生产问题,线上部署6台机器,定时任务A,B都在17:00执行,执行时会各自先获取分布式锁。(服务器时间是一致的)理论上是可以做到同......
  • 【后端面经-java】java线程池满的处理策略
    目录1.线程池介绍1.1基本作用1.2处理流程1.3线程池大小设置1.4线程池参数2.线程池满的处理策略2.1默认--拒绝策略handler3.参考资料1.线程池介绍1.1基本作用对多个线程使用的资源进行集中管理。降低资源消耗:复用线程,降低线程创建和销毁造成的消耗;线程资源管理......
  • 如何获取多线程执行的返回值,多线程的第三种实现方式。
    多线程的第三种实现方式主要有以下步骤。1、创建一个类#MyCallable实现Callable接口。在泛型中指定多线程执行后要返回的数据类型2、在MyCallable方法种重写call方法,此方法的内容,便是多线程的执行内容。类似于run方法。3、将MyCallable对象实例化。4、创建FutureTask<Integer>......
  • 简单记录下 Spring Boot 使用虚拟线程Virtual Threads(Java的协程)的方法
    在之前的文章中,简单描述了将springboot2.x升级springboot3.1的版本的过程。本文将简单介绍如何在spring中引入虚拟线程,在文章最后会放上一些关于虚拟线程的官方参考资料。JDK22会引来重要特性,VirtualThreads也就是协程功能。与主流的async、await方案(C#、JS等语言)相比......
  • [复习随笔]python_dcgan网络复习小知识:模型定义
    定义参数dataroot-thepathtotherootofthedatasetfolder.Wewilltalkmoreaboutthedatasetinthenextsection.workers-thenumberofworkerthreadsforloadingthedatawiththeDataLoader.batch_size-thebatchsizeusedintraining.TheD......