Threads
Exécution concurrente
Threads est une leçon Ruby Academy gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Ruby Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Ruby Academy comprend 4 leçons au total.
Qu’est-ce qu’un fil d’exécution ?
Un fil d’exécution est un chemin d’exécution indépendant au sein de votre programme. Ruby vous permet d’exécuter plusieurs fils d’exécution afin que les tâches puissent se chevaucher dans le temps.
- Le programme principal s’exécute dans le fil d’exécution principal.
- Vous créez d’autres fils d’exécution avec
Thread.new. - Les fils d’exécution partagent la même mémoire : ils peuvent donc lire et modifier les mêmes variables.
Les fils d’exécution sont particulièrement adaptés lorsque votre programme passe du temps à attendre (le réseau, le disque ou une pause), car un fil peut attendre pendant qu’un autre continue à travailler.
Créer un fil d’exécution
Passez un bloc à Thread.new. Le bloc s’exécute dans un nouveau fil d’exécution. Appelez join pour attendre sa fin avant que le programme ne se termine.
t = Thread.new do
puts "Hello from the new thread"
end
t.join
puts "Main thread done"Pourquoi <code>join</code> est important
Lorsque le fil d’exécution principal se termine, Ruby quitte le programme et peut ne pas attendre les autres fils d’exécution. join bloque l’appelant jusqu’à ce que le fil d’exécution cible soit terminé.
Sans join, le fil de travail risque de ne jamais avoir l’occasion d’afficher son résultat avant l’arrêt du programme.
t = Thread.new do
sleep 0.1
puts "Worker finished"
end
puts "Waiting..."
t.join
puts "All done"Plusieurs fils d’exécution à la fois
Vous pouvez lancer un groupe de fils d’exécution, les rassembler dans un tableau, puis appeler join pour chacun d’eux. C’est un schéma courant pour les tâches d’entrée-sortie quasi parallèles.
threads = (1..3).map do |n|
Thread.new do
puts "Thread number " + n.to_s
end
end
threads.each(&:join)
puts "Finished all threads"Partager des variables
Les fils d’exécution partagent la mémoire. Une variable définie avant le fil est visible à l’intérieur de celui-ci. C’est puissant, mais aussi dangereux si deux fils d’exécution écrivent la même valeur.
counter = 0
t = Thread.new do
counter += 1
end
t.join
puts "Counter is " + counter.to_sConditions de concurrence
Une condition de concurrence se produit lorsque des fils d’exécution entrelacent leurs mises à jour de données partagées et que le résultat dépend du moment où elles ont lieu.
counter += 1correspond en réalité à une lecture, une addition, puis une écriture.- Deux fils d’exécution peuvent lire la même ancienne valeur et écrire tous les deux la même nouvelle valeur, ce qui fait perdre une incrémentation.
La solution consiste à coordonner l’accès à l’aide d’un verrou.
Exclusion mutuelle : un verrou
Un Mutex (exclusion mutuelle) garantit qu’un seul fil d’exécution à la fois exécute le code protégé. Encadrez la section critique avec mutex.synchronize.
mutex = Mutex.new
counter = 0
threads = (1..5).map do
Thread.new do
mutex.synchronize do
counter += 1
end
end
end
threads.each(&:join)
puts "Counter is " + counter.to_sRenvoyer une valeur
Thread#value attend la fin du fil d’exécution et renvoie la valeur de son bloc, comme si vous appeliez automatiquement join tout en obtenant un résultat.
t = Thread.new do
2 + 3
end
puts "Result is " + t.value.to_sVariables locales aux fils d’exécution
Chaque fil d’exécution peut stocker ses propres valeurs, indexées par un symbole, avec Thread.current[:key]. Ces valeurs sont privées à ce fil et ne sont jamais partagées.
t = Thread.new do
Thread.current[:name] = "worker"
puts "Inside: " + Thread.current[:name]
end
t.joinGérer les exceptions
Si un fil d’exécution déclenche une erreur, celle-ci reste silencieuse jusqu’à ce que vous appeliez join ou value, ce qui la déclenche à nouveau. Définir Thread.abort_on_exception = true fait immédiatement échouer tout le programme en cas d’erreur, ce qui facilite le débogage.
t = Thread.new do
raise "boom"
end
begin
t.join
rescue => e
puts "Caught: " + e.message
endQuand les fils d’exécution sont utiles
Les fils d’exécution sont très efficaces pour les tâches limitées par les E/S, lorsque le temps est principalement consacré à l’attente. Ils sont moins utiles pour les tâches limitées par le CPU en raison du GVL, que nous étudierons ensuite.
- Adapté : télécharger de nombreuses URL et lire de nombreux fichiers.
- Limité : effectuer des calculs numériques intensifs sur plusieurs cœurs.
Protégez toujours l’état mutable partagé avec un Mutex.
Vérification rapide
Testez votre compréhension des fils d’exécution.
Récapitulatif : fils d’exécution
Vous avez appris les notions essentielles sur les fils d’exécution Ruby :
Thread.newdémarre une exécution concurrente.joinattend ;valueattend et renvoie un résultat.- Les fils d’exécution partagent la mémoire, ce qui peut provoquer des conditions de concurrence.
- Un
Mutexavecsynchronizeprotège l’état partagé. - Les fils d’exécution sont particulièrement performants pour les tâches limitées par les E/S.
Nous allons ensuite voir pourquoi les fils d’exécution ne peuvent pas exploiter pleinement plusieurs cœurs du CPU : le GVL.
Questions Fréquemment Posées
La leçon « Threads » est-elle gratuite ?
Oui — le texte complet de « Threads » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Ruby Academy, passe à CoddyKit PRO. Le cours Ruby Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Threads » ?
Exécution concurrente Tu pratiques Ruby Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Ruby Academy ?
Aucune expérience préalable n'est requise. Ruby Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.
Combien de temps prend la leçon « Threads » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Ruby Academy ?
Oui. Chaque leçon Ruby Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Threads
- Le GVL expliqué
- Fibres
- Ractors