[C++] Detaillierte Erklärung von std::thread

10. September 2023, ab Sonntagnachmittag

Abgeschlossen am Sonntagabend, 10. September 2023, 23:35 Uhr

Obwohl ich heute viel Zeit damit verbracht habe, diesen Blog zu schreiben, habe ich ein umfassendes Verständnis von std::thread.

Allerdings sind einige Inhalte noch nicht perfekt und werden aktualisiert, wenn ich Zeit habe....


Inhaltsverzeichnis


Kopfdatei

#include<Thread>

Mitglieder der Klasse

Typ

id Thread-ID (öffentlicher Mitgliedstyp)

native_handle_type nativer Handle-Typ (öffentlicher Mitgliedstyp)

Methode

(Konstruktor) Thread erstellen (öffentliche Mitgliedsfunktion)

(Destruktor) Thread-Destruktor (öffentliche Member-Funktion)

Operator= Zuweisungsthread verschieben (öffentliche Memberfunktion)

get_id ruft die Thread-ID ab (öffentliche Mitgliedsfunktion)

joinable prüft, ob beigetreten werden kann (öffentliche Memberfunktion)

Join -Thread (öffentliche Member-Funktion)

Separate Threads trennen (öffentliche Memberfunktion)

Swap- Thread (öffentliche Member-Funktion)

native_handle ruft das lokale Handle ab (öffentliche Memberfunktion)

hardware_concurrency [statisch] erkennt Hardware-Parallelität (öffentliche statische Member-Funktion)

(Konstrukteur)

Dieser Konstruktor wird verwendet, um einen Thread zu erstellen und die übergebene Funktion auszuführen

#include <iostream>      
#include<thread> 
void func() 
{
  std::cout << "func executes!" << std::endl;
}

int main() 
{
  std::thread t1(func);
  return 0;
}

Ignorieren Sie hier vorerst das „Beenden, das ohne aktive Ausnahme aufgerufen wird“.

Was heißt Terminate ohne aktive Ausnahme?

„Aufgerufen ohne aktive Ausnahme beenden“ ist eine Ausnahmemeldung, die auftreten kann, wenn ein C++-Programm ausgeführt wird.

Es zeigt an, dass das Programm ohne aktive Ausnahme beendet wurde.

Diese Ausnahme tritt normalerweise unter den folgenden Umständen auf:

  1. Das Programm ruft aktiv std::terminate()eine Funktion auf, um die Ausführung des Programms zu beenden. Dies kann daran liegen, dass das Programm einen Fehler oder eine Ausnahme festgestellt hat, die es nicht verarbeiten kann.
  2. Das Programm wurde aufgrund einer nicht abgefangenen Ausnahme beendet. Wenn ein Programm eine nicht abgefangene Ausnahme auslöst, ruft das System sie auf, std::terminate()um das Programm zu beenden, sofern keine anderen aktiven Ausnahmen vorhanden sind.
  3. Das Programm wird aufgrund bestimmter Beendigungsbedingungen vom Betriebssystem oder anderen externen Faktoren beendet. Beispielsweise kann das Betriebssystem ein Programm aufgrund der Speichernutzung oder anderer Ressourcenbeschränkungen beenden.

operation=

In C++ stellt die Klasse std::thread die Operatorüberladungsfunktion „operator=“ zum Zuweisen eines Thread-Objekts zu einem anderen Thread-Objekt bereit. Verwenden Sie „operator=“, um die Steuerung eines Thread-Objekts auf ein anderes Thread-Objekt zu übertragen und so einen Thread-Austausch oder eine Thread-Übertragung zu realisieren. Dies bedeutet, dass nach dem Aufruf von „operator=“ das ursprüngliche Thread-Objekt die Ausführung beendet und das neue Thread-Objekt mit der Ausführung des zuvor ausgeführten Codes beginnt.

get_id

Mit dieser Methode wird die Thread-ID ermittelt

#include <iostream>      
#include<thread> 
void func() 
{
  std::cout <<"func executes!" << std::endl;
}

int main() 
{
  std::thread t1(func);
  std::cout<<"ID of thread t1 is "<<t1.get_id()<<std::endl;
  return 0;
}

Sie können sehen, dass die Thread-ID 2 ist

fügbar

Was ist Beitritt? Was bedeutet beitreten?

In Threads bedeutet „Join“ das Warten darauf, dass ein Thread die Ausführung abschließt und Ergebnisse zurückgibt, bevor mit der Ausführung des Hauptthreads fortgefahren wird. Wenn der Hauptthread die Join-Methode des Unterthreads aufruft, blockiert der Hauptthread und wartet darauf, dass der Unterthread die Ausführung abschließt. Dadurch wird sichergestellt, dass alle Threads in der erwarteten Reihenfolge ausgeführt werden und das Endergebnis korrekt ist.

Was passiert also, wenn wir Join nicht verwenden?

Der Hauptthread wartet nicht auf den Abschluss des Unterthreads, sodass es möglich ist, dass der Unterthread endet, bevor die Ausführung des Hauptthreads abgeschlossen ist.

#include <iostream>      
#include<thread> 
void func() 
{
  std::cout <<"func executes!" << std::endl;
}

int main() 
{
  std::thread t1(func);
  std::cout<<"ID of thread t1 is "<<t1.get_id()<<std::endl;
  if(t1.joinable())
	std::cout<<"joinable: ture"<<std::endl;
  else
	std::cout<<"joinable: false"<<std::endl;
  return 0;
}

verbinden

Das wurde bereits oben gesagt, deshalb werde ich nicht noch einmal auf Details eingehen.

#include <iostream>      
#include<thread> 
void func() 
{
  std::cout <<"func executes!" << std::endl;
}

int main() 
{
  std::thread t1(func);
  std::cout<<"ID of thread t1 is "<<t1.get_id()<<std::endl;
  if(t1.joinable())
	std::cout<<"joinable: ture"<<std::endl;
  else
	std::cout<<"joinable: false"<<std::endl;
  t1.join();
  return 0;
}

Es ist erwähnenswert, dass es kein „Beenden des Aufrufs ohne aktive Ausnahme“ gibt.

ablösen

Was ist loslösen? Was bedeutet loslösen?

Der Hauptzweck des Trennens von Threads besteht darin, dem Hauptthread die Ausführung anderer Aufgaben zu ermöglichen, während der untergeordnete Thread einige zeitaufwändige Vorgänge ausführt. Durch das Trennen von Threads kann eine Blockierung des Hauptthreads vermieden werden , wodurch die Gesamteffizienz des Programms verbessert wird.

Was ist der Unterschied zwischen der Verwendung von „detach“ und der Nichtverwendung von „join“?

Ich habe es noch nicht herausgefunden ... Ich werde es später aktualisieren, wenn ich es herausgefunden habe

#include <iostream>      
#include<thread> 
void func() 
{
	for(int i=0;i<10000;i++){
		//让线程休眠1秒
		std::this_thread::sleep_for(std::chrono::seconds(1));
		std::cout <<"func executes!" << std::endl;
	}
}

int main() 
{
  std::thread t1(func);
  
  t1.detach();
  
  //让主线程给子线程足够的执行时间
  for(int i=0;i<10000;i++)
	std::this_thread::sleep_for(std::chrono::seconds(1);

  return 0;
}

native_handle

native_handle in der C++-Standardbibliothek ist eine Low-Level-Schnittstelle, die das Handle des zugrunde liegenden Betriebssystems abrufen kann.

native_handle wird hauptsächlich für Low-Level-Szenarien verwendet, die eine direkte Interaktion mit dem Betriebssystem erfordern.

tauschen

Die Funktion swap() besteht darin, die Steuerung zweier Thread-Objekte aufeinander zu übertragen und so den Thread-Austausch zu realisieren. Das bedeutet, dass nach dem Aufruf von swap() beide Threads mit der Ausführung des Codes beginnen, den der andere Thread zuvor ausgeführt hat.

#include <iostream>
#include <thread>

void threadFunction1() {
    // 线程1的代码
    for(int i=0;i<10000;i++){
		//让线程休眠1秒
		std::this_thread::sleep_for(std::chrono::seconds(1));
		std::cout << "Thread 1 is running." << std::endl;
	}
    
}

void threadFunction2() {
    // 线程2的代码
    for(int i=0;i<10000;i++){
		//让线程休眠1秒
		std::this_thread::sleep_for(std::chrono::seconds(1));
		std::cout << "Thread 2 is running." << std::endl;
	}
}

int main() {
    std::thread t1(threadFunction1);  // 创建线程1
    std::thread t2(threadFunction2);  // 创建线程2

    t1.swap(t2);  // 交换线程1和线程2的状态

    t1.join();  // 等待线程1结束
    t2.join();  // 等待线程2结束

    return 0;
}

hardware_concurrency

In C++ ist hardware_concurrency eine Funktion, mit der die Anzahl der auf dem System verfügbaren Prozessorkerne bestimmt wird. Es gibt einen ganzzahligen Wert zurück, der die maximale Anzahl von Threads darstellt, die parallel ausgeführt werden können. Im Allgemeinen hängt der von der Funktion hardware_concurrency() zurückgegebene Wert vom zugrunde liegenden Betriebssystem und der Hardwareplattform ab.

#include <iostream>
#include <thread>

int main() {
    unsigned int numThreads = std::thread::hardware_concurrency();
    std::cout << "Number of available processor cores: " << numThreads << std::endl;

    return 0;
}

Sie sehen, dass meine maximale Anzahl paralleler Threads 8 beträgt, was von der CPU meines Computers bestimmt wird.

Guess you like

Origin blog.csdn.net/m0_61629312/article/details/132790589