首页 > 其他分享 >《信息安全系统设计与实现》第九周学习笔记

《信息安全系统设计与实现》第九周学习笔记

时间:2023-11-01 21:57:23浏览次数:26  
标签:thread int void 信息安全 笔记 线程 pthread mutex 第九


一、 第五章 定时器及时钟服务

1、并行计算

是一种计算方案,它尝试使用多个执行并行算法的处理器更快速的解决问题

顺序算法与并行算法

并行性与并发性

并行算法只识别可并行执行的任务。CPU系统中,并发性是通过多任务处理来实现的

2、线程

线程的原理:某进程同一地址空间上的独立执行单元

线程的优点

线程创建和切换速度更快
线程的响应速度更快
线程更适合并行运算

线程的缺点

线程需要来自用户的明确同步
库函数不安全
单CPU系统中,线程解决问题实际上要比使用顺序程序慢

3、线程操作

线程可在内核模式或用户模式下执行
其中涉及Linux下的pthread并发编程

线程管理函数

创建线程

pthread_create()
int pthread_create(pthread_t *pthread_id,pthread_attr_t *attr,void *(*func)(void*),void *arg)

其中:
1、pthread_id是指向pthread_t类型变量的指针
2、attr如果是NULL,将使用默认属性创建线程

线程ID

int pthread_equal(pthread_t t1,pthread_t t2);

不同的线程,返回0,否则返回非0

线程终止

int pthread_exit(void *status);

线程连接

int pthread_join(pthread_t thread,void **status_ptr)

线程同步

竞态条件:修改结果取决于线程执行顺序

互斥量

在pthread中,锁被称为互斥量

pthread_mutex_lock(&m);
access shared data object;
pthread_mutex_unlock(&m);

死锁预防

死锁是一个状态,在这种状态下,许多执行实体相互等待,无法继续进行下去

条件变量

条件变量可以通过两种方法进行初始化:静态方法,动态方法

生产者-消费者问题

共享全局变量

int buf[NBUF];
int head,tail;
int data;

4.信号量

信号量是进程同步的一般机制
信号量和条件变量

屏障

线程连接操作允许某线程等待其他线程终止
在pthread中可以采用的机制是屏障以及一系列屏障函数

Linux中的线程

进程和线程都是由clone()系统调用创建的具有以下原型

int clone(int (*fn)(void*),void *child_stack,int flags,void *arg)

信号量与条件变量的区别:

条件变量、互斥锁——主要用于线程间通信
pthread_cond_wait()
pthread_cond_wait(&m_cond,&m_mutex); 指的是等待条件变量,总和一个互斥锁结合使用。

pthread_cond_wait() 函数执行时先自动释放指定的互斥锁,然后等待条件变量的变化;在函数调用返回之前(即wait成功获得cond条件的时候),会自动将指定的互斥量重新锁住(即在“等待的条件变量满足条件时,会重新锁住指定的锁”)。

二、代码实践

1、利用线程计算矩阵的和

代码

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

#define ROWS 3
#define COLS 3
#define THREADS_NUM 3

int matrix[ROWS][COLS] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int sum[THREADS_NUM] = {0};
pthread_t threads[THREADS_NUM];

void *thread_func(void *arg) {
    int tid = *(int *)arg;
    int start = tid * ROWS / THREADS_NUM;
    int end = (tid + 1) * ROWS / THREADS_NUM;
    for (int i = start; i < end; i++) {
        for (int j = 0; j < COLS; j++) {
            sum[tid] += matrix[i][j];
        }
    }
    pthread_exit(NULL);
}

int main() {
    int thread_args[THREADS_NUM];
    for (int i = 0; i < THREADS_NUM; i++) {
        thread_args[i] = i;
        pthread_create(&threads[i], NULL, thread_func, &thread_args[i]);
    }
    for (int i = 0; i < THREADS_NUM; i++) {
        pthread_join(threads[i], NULL);
    }
    int total_sum = 0;
    for (int i = 0; i < THREADS_NUM; i++) {
        total_sum += sum[i];
    }
    printf("The sum of the matrix is %d\n", total_sum);
    return 0;
}

代码分析:

该代码中,我们首先定义了一个 3x3 的矩阵和 3 个线程。每个线程计算矩阵的一部分,并将结果存储在 sum 数组中。最后,我们将所有线程计算出的结果相加,得到矩阵的总和。
主函数中:为每个线程创建一个参数数组 thread_args,然后创建 THREADS_NUM 个线程,并将线程 ID 和参数数组传递给线程函数 thread_func。
线程函数中:根据线程 ID 计算出该线程要处理的矩阵部分,然后计算该部分的和并存储在 sum 数组中。
主函数等待所有线程执行完毕后,将 sum 数组中的所有元素相加,得到矩阵的总和,并输出结果。

遇到的问题:

缺少相关的库

2、生产者·消费者问题

代码

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

#define BUFFER_SIZE 5
#define NUM_ITEMS 10

int buffer[BUFFER_SIZE];
int count = 0;
int in = 0;
int out = 0;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t full = PTHREAD_COND_INITIALIZER;
pthread_cond_t empty = PTHREAD_COND_INITIALIZER;

void *producer(void *arg) {
    for (int i = 0; i < NUM_ITEMS; i++) {
        pthread_mutex_lock(&mutex);
        while (count == BUFFER_SIZE) {
            pthread_cond_wait(&full, &mutex);
        }
        buffer[in] = i;
        in = (in + 1) % BUFFER_SIZE;
        count++;
        printf("Produced item: %d\n", i);
        pthread_cond_signal(&empty);
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(NULL);
}

void *consumer(void *arg) {
    for (int i = 0; i < NUM_ITEMS; i++) {
        pthread_mutex_lock(&mutex);
        while (count == 0) {
            pthread_cond_wait(&empty, &mutex);
        }
        int item = buffer[out];
        out = (out + 1) % BUFFER_SIZE;
        count--;
        printf("Consumed item: %d\n", item);
        pthread_cond_signal(&full);
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(NULL);
}

int main() {
    pthread_t producer_thread, consumer_thread;
    pthread_create(&producer_thread, NULL, producer, NULL);
    pthread_create(&consumer_thread, NULL, consumer, NULL);
    pthread_join(producer_thread, NULL);
    pthread_join(consumer_thread, NULL);
    return 0;
}

代码分析

使用一个大小为 BUFFER_SIZE 的缓冲区来模拟生产者和消费者之间的共享数据。生产者线程负责向缓冲区中生产数据,消费者线程负责从缓冲区中消费数据。
生产者线程在每次生产完一个数据项后,会先获取互斥锁 mutex,然后检查缓冲区是否已满(count == BUFFER_SIZE)。如果缓冲区已满,则调用 pthread_cond_wait 函数等待消费者线程发出的非空信号(empty)。一旦收到非空信号,生产者线程将数据写入缓冲区,并更新相关变量。最后,生产者线程发出缓冲区已满的信号(full),释放互斥锁 mutex。
消费者线程的逻辑类似,它在每次消费一个数据项后,会先获取互斥锁 mutex,然后检查缓冲区是否为空(count == 0)。如果缓冲区为空,则调用 pthread_cond_wait 函数等待生产者线程发出的非满信号(full)。一旦收到非满信号,消费者线程从缓冲区中读取数据,并更新相关变量。最后,消费者线程发出缓冲区已空的信号(empty),释放互斥锁 mutex。
在主函数中,我们创建一个生产者线程和一个消费者线程,并使用 pthread_join 函数等待它们的结束。这样,生产者和消费者就可以并发地执行。

显然,输出结果符合预期。生产者线程生产了 10 个数据项,消费者线程消费了这些数据项,并且生产者和消费者交替进行,以避免缓冲区溢出或下溢。
需要注意的是,由于线程的并发执行,生产者和消费者的输出顺序可能会不同,但每个数据项的生产和消费都是正确的。
由于缓冲区大小为 5,因此在生产者和消费者之间存在一定的同步和竞争关系,这也体现了线程间通信和同步的重要性。

三、苏格拉底问答





标签:thread,int,void,信息安全,笔记,线程,pthread,mutex,第九
From: https://www.cnblogs.com/ningxinyu1/p/17804209.html

相关文章

  • 【python爬虫】80页md笔记,0基础到scrapy项目高手,第(3)篇,requests网络请求模块详解
    本文主要学习一下关于爬虫的相关前置知识和一些理论性的知识,通过本文我们能够知道什么是爬虫,都有那些分类,爬虫能干什么等,同时还会站在爬虫的角度复习一下http协议。完整版笔记直接地址:请移步这里共8章,37子模块,总计56668字requests模块本阶段本文主要学习requests这......
  • Linux第九周技术博客
    这周我们学习了进程管理,还学习了一些i/o重定向的内容。每个进程都有唯一的进程标识pid,一个pid只能表示一个进程,ppid为父进程id,需要给该进程分配进程。进程一般分为三种状态:就绪状态、运行状态、阻塞状态。就绪状态不能直接进入阻塞状态,当所有的系统资源都分配出去后因为没有多......
  • 【matlab笔记】杂乱版
    求Lagrange插值多项式symsx;X=[1,3/2,0,2]Y=[3,13/4,3,5/3]n=length(X);L=sym('1');P=sym('0');fori=1:n%求出Li(x)Li=sym('1');forj=1:nifj~=iLi=Li*(x-X(j))/(X(i)-X(j......
  • 网络流笔记
    网络流笔记P2764最小路径覆盖问题对于图上的边\((u,v)\)从\(u\rightarrowv+n\)建\(1\)边\(S\rightarrowu\),\(u\rightarrowT\)建\(1\)边有流量的边为选中的路径,用并查集维护每条链......
  • [学习笔记]TypeScript查缺补漏(二):类型与控制流分析
    @目录类型约束基本类型联合类型控制流分析instanceof和typeof类型守卫和窄化typeof判断instanceof判断in判断内建函数,或自定义函数赋值布尔运算保留共同属性字面量类型(literaltype)asconst作用类型约束TypeScript中的类型是一种用于描述变量、函数参数和函数返回值的特征的方......
  • celery学习md笔记:从0基础到系统性掌握用法 第(2)篇:celery的配置
    Celery是一个功能完备即插即用的任务队列。它使得我们不需要考虑复杂的问题,使用非常简单。celery看起来似乎很庞大,本文我们先对其进行简单的了解,然后再去学习其他一些高级特性。完整版笔记直接地址:请移步这里共4章,12子模块,总计5628字本章节我们需要快速了解celery一......
  • 第九次上课
    在本次课程当中学习了进程管理,学习了psaux查看静态进程,ps--sort -%cpu按照cpu占用cpu占用百分比的降序排列,ps-ef命令查看uid,pid,ppidtop命名是查看动态地的显示进程,类似于系统中的任务管理器。按M键以内存占用率排序,P键按CPU占用率排序,N键以PID数值大小排序,R键对排序进行......
  • 学习笔记:关于MySQL的相关基础
    showdatabases;showtablesfrominformation_schema;--测试一下注释#注释第二种--列出所有的数据库SHOWdatabases;--查看某一个数据库里面所有的表USEdatabasename;usemysql;showtables;showtablesfrommysql;--select特殊应用查看当前时......
  • 【刷题笔记】93. Restore IP Addresses
    题目Givenastringcontainingonlydigits,restoreitbyreturningallpossiblevalidIPaddresscombinations.Example:Input:"25525511135"Output:["255.255.11.135","255.255.111.35"]题目大意给定一个只包含数字的字符串,复原它并返回所有可能的IP地址格式。......
  • 《程序员修炼之道:从小工到专家》阅读笔记(6)
    31靠巧合编程:需要避免一种编程方式,是指由于偶然原因导致一段代码能够正常工作,而非因为良好的设计原则。这可能导致难以维护、难以理解的代码,以及难以预测的副作用。要确保编程时明确知道代码执行过程和目的,理解各模块之间的依赖关系,并遵循最佳实践。32算法效率:在不同数据规模下......