Documentos de Académico
Documentos de Profesional
Documentos de Cultura
GUÍA DE LABORATORIO
INFORMACIÓN BÁSICA
ASIGNATURA: Sistemas Operativos
TÍTULO DE LA
Threads en C++
PRÁCTICA:
NÚMERO DE NRO.
9 AÑO LECTIVO: 2023 B
PRÁCTICA: SEMESTRE:
INDIVIDUAL X
TIPO DE
MÍNIMO DE MÁXIMO DE
PRÁCTICA: GRUPAL 10 15
ESTUDIANTES ESTUDIANTES
FECHA INICIO: 30/10/2023 FECHA FIN: 03/11/2023 DURACIÓN: 2 horas
RECURSOS Y EQUIPOS A UTILIZAR:
Ubuntu Linux, g++, Computador personal, lapiz, papel
DOCENTE(s):
Msc Roni Guillermo Apaza Aceituno
OBJETIVOS/TEMAS Y COMPETENCIAS
OBJETIVOS:
- Implementar threads usando c++
- Utilizar las principales funciones de la librería thread
TEMAS:
• Librería thread en c++
• Funciones de thread en c++
• Programación concurrente
CONTENIDO DE LA GUÍA
I MARCO CONCEPTUAL
Threads
¿Qué son los threads, o hilos? A la hora de crear un programa, generalmente nos encontraremos con que
nuestro programa ejecuta las instrucciones en orden, una por una. Esto es correcto, hasta el momento en
que necesitamos hacer varias tareas a la vez, ya sea por necesidad, por acelerar un proceso, o cualquier otra
razón que se nos presente. Es en este punto, en que podemos utilizar los llamados "hilos" ("threads", por su
nombre en inglés, y que usaré a partir de ahora).
Un thread se ejecutará de forma paralela a nuestro programa principal, ejecutando las mismas instrucciones
u otras. Un thread tiene un comienzo (normalmente, cuando es creado), y tiene un final, que suele ser
cuando ha terminado su propósito. Es posible tener todos los threads que se deseen a la vez. La única
limitación será la que pudiese poner el Sistema Operativo y la lógica. También hay que tener en cuenta, que
no por tener más threads van a ir los procesos necesariamente más rápido.
Antes de empezar con ellos, una anotación más: Los threads pueden compartir recursos. Por ejemplo, en C++,
si tenemos una variable global y lanzamos un thread, ese thread puede acceder también a ella. Es
importante tener en cuenta que si dos threads acceden a la vez al mismo recurso (especialmente si lo van a
modificar), se pueden generar un comportamiento "aleatorio" ya que quizás un thread lo modifique primero
y luego el otro, o viceversa. Lo mismo va para funciones y clases que trabajen con streams, como es hacer
"cout << var;". Esto no lo voy a extender en esta entrada, pero aviso de forma anticipada de posibles
problemas que pudiera ocurrir.
Dicho esto, vamos al código. Utilizaremos la librería <thread>, y de esta, la clase std::thread. La clase thread,
tras ser construida, generará un thread, sin necesidad de llamar a ningún método suyo. Digo esto, porque en
otros lenguajes, como Java, nos podemos encontrar con que haya que llamar a algún método suyo para
iniciarlo.
El constructor de thread que utilizaremos, recibe de primer argumento, la función que ejecutará. Véase que
los threads ejecutarán una función. Cuando termine la función, el thread terminará.
Funciones miembro
detach: Desasocia el subproceso asociado del objeto thread.
get_id: Devuelve el identificador único del subproceso asociado.
hardware_concurrency: Estática. Devuelve una estimación del número de contextos de subprocesos
de hardware.
join: Se bloquea hasta que el subproceso asociado se completa.
joinable: Especifica si se puede unir el subproceso asociado.
native_handle: Devuelve el tipo específico de la implementación que representa el identificador de
subproceso.
swap: Intercambia el estado de objeto con un objeto thread especificado.
II EJERCICIO RESUELTO
Ejercicio 1.
UNIVERSIDAD NACIONAL DE SAN AGUSTIN
FACULTAD DE INGENIERÍA DE PRODUCCIÓN Y SERVICIOS
ESCUELA PROFESIONAL DE INGENIERÍA DE SISTEMA
Implementar dos threads usando la librería thread de c++, guardar el programa con el nombre de
ejercicio01.cpp:
#include <iostream>
#include <thread>
void foo(){
std::cout<<"estoy en foo";
}
void bar(){
std::cout<<"estoy en bar";
}
int main(){
std::thread th(foo);
std::thread hr(bar);
th.join();
hr.join();
}
/* Crear una clase con funciones miembro, que sean llamadas por un thread */
Ejercicio 2.
Crear un programa que implemente dos threads y muestre sus IDs, guardar el programa con el nombre de
ejercicio02.cpp:
#include <chrono>
#include <iostream>
#include <thread>
using namespace std;
int main()
{
// creando thread1 y thread2
thread thread1(sleepThread);
UNIVERSIDAD NACIONAL DE SAN AGUSTIN
FACULTAD DE INGENIERÍA DE PRODUCCIÓN Y SERVICIOS
ESCUELA PROFESIONAL DE INGENIERÍA DE SISTEMA
thread thread2(sleepThread);
thread1.join();
thread2.join();
return 0;
}
Ejercicio 3.
Crear dos threads en un programa en C++ que tengan cada uno una variable estática, guardar el programa
con el nombre de ejercicio03.cpp:
void thread_func()
{
// variable estatica para thread-local
static thread_local int stls_variable = 0;
// Incrementa la variable
stls_variable += 1;
int main()
{
thread t1(thread_func);
thread t2(thread_func);
UNIVERSIDAD NACIONAL DE SAN AGUSTIN
FACULTAD DE INGENIERÍA DE PRODUCCIÓN Y SERVICIOS
ESCUELA PROFESIONAL DE INGENIERÍA DE SISTEMA
t1.join();
t2.join();
return 0;
}
Ejercicio 4.
Crear el siguiente programa en c++, donde se crean 2 threads que incrementan cada uno sus contadores y
que muestren también su ID, guarde este programa con el nombre de ejercicio04.cpp, compilelo.
void increment_counter()
{
counter++;
cout << "Thread " << this_thread::get_id()
<< " counter = " << counter << endl;
}
int main()
{
// Crear el primer thread
thread t1(increment_counter);
// Crear el segundo thread
thread t2(increment_counter);
// Esperar por el primer thread para finalizar
t1.join();
// Esperar por el segundo thread para finalizar
t2.join();
return 0;
}
Ejercicio 5.
Crear el siguiente programa en c++, donde se muestra el uso de un thread para aplicarlo sobre una clase,
guárdelo como ejercicio05.cpp
class Singleton {
public:
static Singleton& getInstance()
{
// Cada thread tendria su propia instancia de
// Singleton
thread_local Singleton instance;
return instance;
}
void printMessage()
{
cout << "Hola desde el thread "
<< this_thread::get_id() << endl;
}
private:
Singleton() = default;
};
void workerThread()
{
Singleton::getInstance().printMessage();
}
int main()
{
// Crear el primer thread
thread t1(workerThread);
// Crear el segundo thread
thread t2(workerThread);
return 0;
}
Ejercicio 6.
El siguiente programa muestra como la función detach() puede cumplir la misma caracteristicas de join(),
guarde el programa con el nombre de ejercicio06.cpp, compílelo
#include <iostream>
#include <thread>
void thread_function()
{
std::cout << "funcion Thread\n";
}
int main()
{
std::thread t(&thread_function);
std::cout << "Thread principal\n";
// t.join();
t.detach();
return 0;
}
Ejercicio 7
El siguiente programa demuestra que no se puede usar detach() y join() al mismo tiempo, guarde el
programa con el nombre de ejercicio07.cpp, compílelo
#include <iostream>
#include <thread>
void thread_function()
{
std::cout << "funcion Thread\n";
}
int main()
{
std::thread t(&thread_function);
UNIVERSIDAD NACIONAL DE SAN AGUSTIN
FACULTAD DE INGENIERÍA DE PRODUCCIÓN Y SERVICIOS
ESCUELA PROFESIONAL DE INGENIERÍA DE SISTEMA
Ejercicio 8.
Crear el siguiente programa en cpp, adiciona un thread, solo si tiene la capacidad de ser adicionado
(joinable), llamelo ejercicio08.cpp, compílelo
#include <iostream>
#include <thread>
void thread_function()
{
std::cout << "funcion Thread\n";
}
int main()
{
std::thread t(&thread_function);
std::cout << "Thread principal\n";
// t.join();
if(t.joinable())
t.join();
return 0;
}
Ejercicio 9
Crear el siguiente programa en c++, que pasa parametros usando una referencia, llamelo ejercicio09.cpp,
compílelo
#include <iostream>
#include <thread>
#include <string>
void thread_function(std::string s)
{
std::cout << "función thread ";
UNIVERSIDAD NACIONAL DE SAN AGUSTIN
FACULTAD DE INGENIERÍA DE PRODUCCIÓN Y SERVICIOS
ESCUELA PROFESIONAL DE INGENIERÍA DE SISTEMA
int main()
{
std::string s = "Kathy Perry";
std::thread t(&thread_function, s);
std::cout << "el mensaje del thread principal es = " << s << std::endl;
t.join();
return 0;
}
Ejercicio 10
Crear el siguiente programa en c++, que copia el contenido de un thread a otro thread ejercicio10.cpp,
compílelo
#include <iostream>
#include <thread>
void thread_function()
{
std::cout << "thread function\n";
}
int main()
{
std::thread t(&thread_function);
std::cout << "main thread\n";
std::thread t2 = move(t);
t2.join();
return 0;
}
Ejercicio 11
Crear el siguiente programa en c++, que muestra la cantidad de threads que se pueden ejecutar en una cpu,
llamelo ejercicio11.cpp, compílelo
UNIVERSIDAD NACIONAL DE SAN AGUSTIN
FACULTAD DE INGENIERÍA DE PRODUCCIÓN Y SERVICIOS
ESCUELA PROFESIONAL DE INGENIERÍA DE SISTEMA
#include <iostream>
#include <thread>
int main()
{
std::cout << "Numero de threads = "
<< std::thread::hardware_concurrency() << std::endl;
return 0;
}
Ejercicio 12
Crear el siguiente programa en c++, que crea un thread recibiendo parametros, llamelo ejercicio12.cpp,
compílelo
#include <iostream>
#include <thread>
int main(){
thread th(func, 1, 5.7);
if(th.joinable()) {
th.join();
}
}
IV CUESTIONARIO
1 ¿La función sleep_until() es similar a sleep for()?
2 ¿La versión 17 de c++ podría compilar los codigos mostrados en esta guia?