两个线程thread1和thread2所执行的函数,以及在执行这两个线程之前的初始化代码init,如下面代码段所示。如果我们需要保证两个线程都一定可以终止运行。请填写下面代码中空出的部分。注意,在thread1与thread2函数中,每个空位上只能填写信号量的signal()和wait()操作,但操作数量不限。
时间: 2023-05-02 07:04:20 浏览: 191
题目中给出了两个线程 thread1 和 thread2,以及它们所执行的函数。下面是初始代码的一部分,其中空出了一些部分。注意,在 thread1 和 thread2 函数中,每个空位上只能填写信号量的 signal() 和 wait() 操作,但是操作次数没有限制。
相关问题
本关的编程任务是补全右侧代码片段中Begin至End中间的代码,具体要求如下: 补全ThreadHandler1和ThreadHandler2函数中代码,使用信号量来同步这两个线程(两个线程相互交替执行),使其执行顺序为ThreadHandler1 > ThreadHandler2 > ThreadHandler1...; 信号量sem1被初始化为1,信号量sem2被初始化为0; 提示:参考相关知识中的信号量同步多线程内容;写个实验报告
以下是针对本关编程任务的代码实现和实验报告。
## 代码实现
```c++
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
#include <semaphore.h>
using namespace std;
sem_t sem1, sem2;
void ThreadHandler1()
{
while (true)
{
sem_wait(&sem1);
cout << "ThreadHandler1" << endl;
sem_post(&sem2);
}
}
void ThreadHandler2()
{
while (true)
{
sem_wait(&sem2);
cout << "ThreadHandler2" << endl;
sem_post(&sem1);
}
}
int main()
{
sem_init(&sem1, 0, 1);
sem_init(&sem2, 0, 0);
thread t1(ThreadHandler1);
thread t2(ThreadHandler2);
t1.join();
t2.join();
sem_destroy(&sem1);
sem_destroy(&sem2);
return 0;
}
```
## 实验报告
### 实验目的
1. 了解信号量在多线程同步中的应用;
2. 掌握使用信号量实现多线程同步的方法和技术;
3. 熟悉信号量同步中的常见问题和解决方法。
### 实验原理
信号量是一种用于进程/线程同步的机制,它可以用来实现进程/线程之间的同步和互斥访问。信号量包括两种类型:二元信号量和计数信号量。二元信号量只有两种状态,一般用于互斥访问;计数信号量可以有多种状态,用于实现同步和互斥访问。
在本实验中,我们通过使用信号量来同步两个线程,使其交替执行。具体来说,我们使用两个信号量sem1和sem2来实现同步,其中sem1初始值为1,sem2初始值为0。当线程1执行完毕后,它会释放sem2信号量,使得线程2可以执行。当线程2执行完毕后,它会释放sem1信号量,使得线程1可以再次执行。
### 实验过程
首先,我们在主函数中初始化两个信号量sem1和sem2:
```c++
sem_init(&sem1, 0, 1);
sem_init(&sem2, 0, 0);
```
然后,我们创建两个线程t1和t2,并分别将ThreadHandler1和ThreadHandler2函数作为线程的执行函数:
```c++
thread t1(ThreadHandler1);
thread t2(ThreadHandler2);
```
在ThreadHandler1函数中,我们使用sem_wait函数等待sem1信号量,然后输出"ThreadHandler1"字符串,最后使用sem_post函数释放sem2信号量。在ThreadHandler2函数中,我们使用sem_wait函数等待sem2信号量,然后输出"ThreadHandler2"字符串,最后使用sem_post函数释放sem1信号量。
```c++
void ThreadHandler1()
{
while (true)
{
sem_wait(&sem1);
cout << "ThreadHandler1" << endl;
sem_post(&sem2);
}
}
void ThreadHandler2()
{
while (true)
{
sem_wait(&sem2);
cout << "ThreadHandler2" << endl;
sem_post(&sem1);
}
}
```
最后,我们在主函数中等待两个线程执行完毕,并销毁两个信号量:
```c++
t1.join();
t2.join();
sem_destroy(&sem1);
sem_destroy(&sem2);
```
### 实验总结
本实验通过使用信号量来实现多线程同步,使得两个线程可以交替执行。在实际应用中,需要根据具体的需求选择适当的同步方法,以保证程序的正确性和效率。同时,也需要注意信号量同步中可能出现的死锁和饥饿问题,以及如何解决这些问题。
在RT-Thread中的线程时间片轮转调度中,其中线程thread1和线程thread2共用一个入口函数thread entry,thread1的时间片为10,thread2的时间片为5,用输入参数parameter,在thread entry函数中添加代码 (if判断语句),实现线程1和线程2运行态分别在flag1和flag2周期在0和1两个状态交替转换,并在虚拟逻辑分析仪中添加flag1和flag2的bit观察点;添加代码实现创建第3个线程thread,优先级与前2个任务相同,时间片与任务2相同。入口函数依然使用thread entry函数。并在thread entry函数中添加代码,实现与前两个任务类似的fag3。在合适位置设置断点,观察任务3状态在就绪、运行和挂起之间的转换;在入口函数中打印当前在运行的线程状态;通过设置断点和逻辑分析仪观察分析3个线程的运行时间和顺序,计算分析3个任务的占用cpu的时间比例,要求条理清晰明了。
下面是实现该功能的代码示例:
```c
#include <rtthread.h>
// flag1和flag2分别表示线程1和线程2的状态
static int flag1 = 0;
static int flag2 = 1;
static int flag3 = 0;
static void thread_entry(void *parameter)
{
int thread_id = (int)parameter;
while (1)
{
if (thread_id == 1)
{
flag1 = !flag1;
}
else if (thread_id == 2)
{
flag2 = !flag2;
}
else if (thread_id == 3)
{
flag3 = !flag3;
}
rt_thread_mdelay(10);
}
}
int rt_application_init(void)
{
rt_thread_t thread1, thread2, thread3;
thread1 = rt_thread_create("thread1", thread_entry, (void *)1, 1024, 10, 10);
if (thread1 != RT_NULL)
{
rt_thread_startup(thread1);
}
thread2 = rt_thread_create("thread2", thread_entry, (void *)2, 1024, 10, 5);
if (thread2 != RT_NULL)
{
rt_thread_startup(thread2);
}
thread3 = rt_thread_create("thread3", thread_entry, (void *)3, 1024, 10, 5);
if (thread3 != RT_NULL)
{
rt_thread_startup(thread3);
}
while (1)
{
rt_kprintf("current running thread: %s\n", rt_thread_self()->name);
rt_thread_mdelay(1000);
}
return 0;
}
```
在该代码中,我们创建了三个线程 thread1、thread2 和 thread3,它们都共用一个入口函数 thread_entry。在该函数中,我们使用输入参数 parameter 来区分不同的线程。然后根据输入的线程id,分别在不同的时间片周期中将 flag1、flag2 或 flag3 状态取反。
在初始化函数 rt_application_init 中,我们先创建了 thread1 和 thread2 两个线程,并分别给它们设置不同的时间片和优先级。然后创建了 thread3 线程,也设置了它的时间片与 thread2 相同。
在 while 循环中,我们不断打印当前正在运行的线程的名称,用于观察线程的运行状态。同时,我们也使用 rt_thread_mdelay 函数来延时一段时间,以便线程能够切换运行态和就绪态。
在虚拟逻辑分析仪中,我们添加了 flag1、flag2 和 flag3 的 bit 观察点,用于观察不同线程的状态变化。通过设置断点和逻辑分析仪观察分析三个线程的运行时间和顺序,可以计算分析三个任务的占用 CPU 的时间比例。
阅读全文