recherche
Maisondéveloppement back-endTutoriel C#.NetAuto-apprentissage C#12 à partir de 0 - Un résumé des solutions de synchronisation de threads et de leurs avantages et inconvénients

Tout d'abord, une chose est sûre : la bibliothèque de classes Framework (FCL) de Microsoft garantit que toutes les méthodes statiques sont thread-safe.

FCL ne garantit pas que les méthodes d'instance sont thread-safe. Parce que si tous les verrous sont ajoutés, cela entraînera une énorme perte de performances. De plus, si chaque méthode d'instance doit acquérir et libérer un verrou, vous vous retrouverez en fait avec un seul thread exécuté dans votre application à un moment donné, ce qui a un impact évident sur les performances.

Ce qui suit présente la construction primitive de synchronisation des threads.

Primitives : font référence aux constructions les plus simples pouvant être utilisées dans le code. Il existe deux constructions primitives : le mode utilisateur et le mode noyau.

Le mode utilisateur

utilise des instructions spéciales du processeur pour coordonner les threads.

Technologie : mot-clé volatile, classe Interlocked (interlock), spinlock (spin lock)

Verrouillage commun ① : mot-clé volatile indique qu'un champ peut être modifié par plusieurs threads s'exécutant simultanément. Les champs déclarés volatils ne sont pas soumis aux optimisations du compilateur (en supposant un accès par un seul thread). Cela garantit que le champ présente la dernière valeur à tout moment.

Classe interverrouillée : fournit des opérations atomiques pour les variables partagées par plusieurs threads. . L'opération dite atomique fait référence à une opération qui ne sera pas interrompue par le mécanisme de planification des threads ; une fois cette opération lancée, elle s'exécutera jusqu'à la fin sans aucun changement de contexte (passage à un autre thread) au milieu.

Verrous communs ② : La structure SpinLock est une primitive de synchronisation mutex de bas niveau qui tourne en attendant d'acquérir un verrou. Sur les ordinateurs multicœurs, SpinLock fonctionnera mieux que les autres types de verrous lorsque les temps d'attente sont censés être courts et que les conditions de conflit sont rares. Même si SpinLock n'acquiert pas le verrou, il génère la tranche de temps du thread. Cela permet d'éviter l'inversion de la priorité des threads et de permettre au garbage collector de continuer à s'exécuter. Lorsque vous utilisez SpinLock, assurez-vous qu'aucun thread ne maintient le verrou pendant plus d'une très courte période de temps et qu'aucun thread ne se bloque pendant le maintien du verrou.

Avantages :

Les constructions primitives en mode utilisateur doivent être utilisées autant que possible, car elles sont nettement plus rapides que les constructions en mode noyau.

La coordination des threads se fait au niveau matériel (c'est pourquoi elle est si rapide).

Mais le système d'exploitation Microsoft Windows ne détecte jamais qu'un thread est bloqué sur une construction primitive en mode utilisateur.

Puisqu'un pool de threads bloquant sur une construction primitive en mode utilisateur n'est jamais considéré comme bloqué, le pool de threads ne créera pas de nouveau thread pour remplacer un tel thread temporaire.

Ces instructions CPU ne bloquent le thread que pendant une période de temps relativement courte.

Inconvénients :

Seul le noyau du système d'exploitation Windows peut arrêter l'exécution d'un thread (l'empêchant de perdre du temps CPU).

Les threads exécutés en mode utilisateur peuvent être préemptés par le système, mais les threads seront à nouveau programmés le plus rapidement possible.

Les threads qui souhaitent obtenir des ressources mais ne peuvent pas les obtenir temporairement continueront à « tourner » en mode utilisateur, ce qui peut faire perdre beaucoup de temps CPU. Les threads s'exécutent toujours sur un seul processeur, que nous appelons « livelock ».

Instance :

using System;using System.Threading;public class Worker
{    // This method is called when the thread is started.
    public void DoWork()
    {        while (!_shouldStop)
        {
            Console.WriteLine("Worker thread: working...");
        }
        Console.WriteLine("Worker thread: terminating gracefully.");
    }    public void RequestStop()
    {
        _shouldStop = true;
    }    // Keyword volatile is used as a hint to the compiler that this data
    // member is accessed by multiple threads.
    private volatile bool _shouldStop;
}public class WorkerThreadExample
{    static void Main()
    {        // Create the worker thread object. This does not start the thread.
        Worker workerObject = new Worker();
        Thread workerThread = new Thread(workerObject.DoWork);        // Start the worker thread.
        workerThread.Start();
        Console.WriteLine("Main thread: starting worker thread...");        // Loop until the worker thread activates.
        while (!workerThread.IsAlive) ;        // Put the main thread to sleep for 1 millisecond to
        // allow the worker thread to do some work.
        Thread.Sleep(1);        // Request that the worker thread stop itself.
        workerObject.RequestStop();        // Use the Thread.Join method to block the current thread 
        // until the object's thread terminates.
        workerThread.Join();
        Console.WriteLine("Main thread: worker thread has terminated.");
    }    // Sample output:
    // Main thread: starting worker thread...
    // Worker thread: working...
    // Worker thread: working...
    // Worker thread: working...
    // Worker thread: working...
    // Worker thread: working...
    // Worker thread: working...
    // Worker thread: terminating gracefully.
    // Main thread: worker thread has terminated.}

Mode noyau

Fourni par le système d'exploitation Windows lui-même. Ils nécessitent l'appel de fonctions implémentées par le noyau du système d'exploitation dans le thread de l'application.

Technologie : EventWaitHandle (événement), Semaphore (sémaphore), Mutex (mutex)

System.Object  
System.MarshalByRefObject    
System.Threading.WaitHandle      
System.Threading.EventWaitHandle      
System.Threading.Mutex      
System.Threading.Semaphore

Verrous communs ③ : La classe Mutex est un wrapper de la construction Win32, qui peut être utilisé entre les applications Le marshaling aux limites du domaine du programme peut être utilisé pour plusieurs attentes et peut être utilisé pour synchroniser les threads dans différents processus.

Avantages :

Lorsqu'un thread acquiert des ressources appartenant à d'autres threads via des constructions en mode noyau, Windows bloque le thread pour l'empêcher de perdre du temps CPU. Lorsque la ressource devient disponible, Windows reprend le thread, lui permettant d'accéder à la ressource. Il n'occupe pas de "spin" CPU.

Permet de synchroniser les threads natifs et gérés les uns avec les autres.

Les threads exécutés dans différents processus sur la même machine peuvent être synchronisés.

Des paramètres de sécurité peuvent être appliqués pour empêcher les comptes non autorisés d'y accéder.

Un thread peut bloquer jusqu'à ce que toutes les constructions en mode noyau avec lesquelles il coopère soient disponibles, ou jusqu'à ce qu'une construction en mode noyau de l'ensemble soit disponible.

Les threads bloqués sur les constructions en mode noyau peuvent spécifier une valeur de délai d'attente : si la ressource souhaitée n'est pas accessible dans le délai spécifié, le thread peut être débloqué et effectuer d'autres tâches.

Inconvénients :

Le passage d'un thread du mode utilisateur au mode noyau (ou vice versa) entraîne une énorme pénalité de performances, c'est exactement pourquoi les constructions du noyau doivent être évitées. De plus, si le thread est bloqué tout le temps, cela entraînera un « deadlock » (deadlock).

Le blocage est toujours dû au livelock, car le livelock gaspille du temps CPU et de la mémoire (pile de threads, etc.), tandis que le blocage ne fait que gaspiller de la mémoire.

Construction hybride

兼具上面两者的长处。在没有竞争的情况下,快而且不会阻塞(就像用户模式)。在有竞争的情况,希望它被操作系统内核阻塞。

技术:ManualResetEventSlim类、SemaphoreSlim类、Monitor类、Lock类、ReaderWriterLockSlim类、CountdownEvent类、Barrier类、双检锁.

常见锁④:Monitor 通常更为可取,因为监视器是专门为 .NET Framework 而设计的,因而它比Mutex可以更好地利用资源。尽管 mutex 比监视器更为强大,但是相对于 Monitor 类,它所需要的互操作转换更消耗计算资源。

常见锁⑤:使用 lock (C#) 或 SyncLock (Visual Basic) 关键字是Monitor的封装。通常比直接使用 Monitor 类更可取,一方面是因为 lock 或 SyncLock 更简洁,另一方面是因为lock 或 SyncLock 确保了即使受保护的代码引发异常,也可以释放基础监视器。

常见锁⑥:ReaderWriterLock 锁,在某些情况下,可能希望只在写入数据时锁定资源,在不更新数据时允许多个客户端同时读取数据。ReaderWriterLock 类在线程修改资源时将强制其独占访问资源,但在读取资源时则允许非独占访问。 ReaderWriter 锁可用于代替排它锁。使用排它锁时,即使其他线程不需要更新数据,也会让这些线程等待。

双检锁

常见锁⑦:双重检查锁定模式(也被称为”双重检查加锁优化”,”锁暗示”(Lock hint)) 是一种软件设计模式用来减少并发系统中竞争和同步的开销。

双重检查锁定模式首先验证锁定条件(第一次检查),只有通过锁定条件验证才真正的进行加锁逻辑并再次验证条件(第二次检查)。

它通常用于减少加锁开销,尤其是为多线程环境中的单例模式实现“惰性初始化”。惰性初始化的意思是直到第一次访问时才初始化它的值。

public sealed class Singleton
    {        private static volatile Singleton instance = null;        
private static object syncRoot = new Object();        
private static int count = 100;        
private Singleton() { }        
public static Singleton Instance
        {            get
            {                if (instance == null)
                {                    lock (syncRoot)
                    {                        if (instance == null)
                            instance = new Singleton();
                    }
                }                return instance;
            }
        }        public static Singleton GetSingleton()
        {            if (instance == null)
            {                lock (syncRoot)
                {                    if (instance == null)
                    {
                        instance = new Singleton();
                    }                        
                }
            }            return instance;
        }        public override string ToString()
        {            lock (syncRoot)
            {                int buf = --count;
                Thread.Sleep(20);                return buf + "_" + count.ToString();
            }
        }
    }static void Main(string[] args)
        {
            Task<string>[] tasks = new Task<string>[10];
            Stopwatch watch = new Stopwatch();            object syncRoot = new Object();
            watch.Start();            for (int i = 0; i < tasks.Length; i++)
            {
                tasks[i] = Task.Factory.StartNew<string>(() =>(Singleton.GetSingleton().ToString()));                    
            }
            Task.WaitAll(tasks, 5000);//设置超时5s
            watch.Stop();
            Console.WriteLine("Tasks running need " + watch.ElapsedMilliseconds + " ms." + "\n");            
for (int i = 0; i < tasks.Length; i++)
            {                //超时处理
                if (tasks[i].Status != TaskStatus.RanToCompletion)
                {
                    Console.WriteLine("Task {0} Error!", i + 1);
                }                else
                {                    //save result
                    Console.WriteLine("Tick ID is " + tasks[i].Result);
                    Console.WriteLine();
                }
            }            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine("Main thread do work!");
                Thread.Sleep(200);
            }

            Console.ReadKey();
        }

输出:

Tasks running need 298 ms.

Tick ID is 96_96

Tick ID is 99_99

Tick ID is 97_97

Tick ID is 98_98

Tick ID is 95_95

Tick ID is 94_94

Tick ID is 93_93

Tick ID is 92_92

Tick ID is 91_91

Tick ID is 90_90

Main thread do work!
Main thread do work!
Main thread do work!

以上就是从0自学C#12--线程同步解决方法汇总以及优缺点的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Déclaration
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
C # et .NET: Comprendre la relation entre les deuxC # et .NET: Comprendre la relation entre les deuxApr 17, 2025 am 12:07 AM

La relation entre C # et .NET est inséparable, mais ce ne sont pas la même chose. C # est un langage de programmation, tandis que .NET est une plate-forme de développement. C # est utilisé pour écrire du code, compiler dans le langage intermédiaire de .NET (IL) et exécuté par .NET Runtime (CLR).

La pertinence continue de C # .net: un regard sur l'utilisation actuelleLa pertinence continue de C # .net: un regard sur l'utilisation actuelleApr 16, 2025 am 12:07 AM

C # .NET est toujours important car il fournit des outils et des bibliothèques puissants qui prennent en charge le développement d'applications multiples. 1) C # combine .NET Framework pour rendre le développement efficace et pratique. 2) Le mécanisme de collecte de la sécurité et des ordures de C # améliore ses avantages. 3) .NET fournit un environnement de course multiplateforme et des API riches, améliorant la flexibilité du développement.

Du Web au bureau: la polyvalence de C # .netDu Web au bureau: la polyvalence de C # .netApr 15, 2025 am 12:07 AM

C # .NETtisversatileforbothwebandDeskTopDevelopment.1) forweb, useasp.netfordynamicapplications.2) fordesktop, employwindowsformSorwpfforrichInterfaces.3) usexamarinforcross-plateformDevelopment, permanant les codéescosswindows, macos, linux, etmobiledevices.

C # .NET et l'avenir: s'adapter aux nouvelles technologiesC # .NET et l'avenir: s'adapter aux nouvelles technologiesApr 14, 2025 am 12:06 AM

C # et .NET s'adaptent aux besoins des technologies émergentes à travers des mises à jour et des optimisations continues. 1) C # 9.0 et .NET5 introduire le type d'enregistrement et l'optimisation des performances. 2) .netcore améliore le support natif et conteneurisé cloud. 3) ASP.Netcore s'intègre aux technologies Web modernes. 4) ML.NET prend en charge l'apprentissage automatique et l'intelligence artificielle. 5) La programmation asynchrone et les meilleures pratiques améliorent les performances.

C # .NET vous convient-il? Évaluer son applicabilitéC # .NET vous convient-il? Évaluer son applicabilitéApr 13, 2025 am 12:03 AM

C # .NeTissuitableFormenterprise-LevelApplications withithemicrosofosystématetoitsstrongThpyping, RichLibrary, androbustperformance.wowever, itmayNotBeidealForcross-PlatformDevelopmentorwhenRawpeediscritical, whileLanguageSlikerUstorGomightBeferable.

C # code dans .NET: Explorer le processus de programmationC # code dans .NET: Explorer le processus de programmationApr 12, 2025 am 12:02 AM

Le processus de programmation de C # dans .NET comprend les étapes suivantes: 1) l'écriture de code C #, 2) la compilation dans un langage intermédiaire (IL) et 3) l'exécution par .NET Runtime (CLR). Les avantages de C # dans .NET sont sa syntaxe moderne, son système de type puissant et son intégration serrée avec le Framework .NET, adapté à divers scénarios de développement des applications de bureau aux services Web.

C # .NET: Explorer les concepts de base et les principes fondamentaux de la programmationC # .NET: Explorer les concepts de base et les principes fondamentaux de la programmationApr 10, 2025 am 09:32 AM

C # est un langage de programmation moderne et orienté objet développé par Microsoft et dans le cadre du .NET Framework. 1.C # prend en charge la programmation orientée objet (POO), y compris l'encapsulation, l'héritage et le polymorphisme. 2. La programmation asynchrone en C # est implémentée via Async et attend des mots clés pour améliorer la réactivité des applications. 3. Utilisez LINQ pour traiter les collections de données concisement. 4. Les erreurs courantes incluent les exceptions de référence NULL et les exceptions indexes hors gamme. Les compétences de débogage comprennent l'utilisation d'un débogueur et une gestion des exceptions. 5. L'optimisation des performances comprend l'utilisation de StringBuilder et d'éviter l'emballage et le déballage inutiles.

Test C # .NET Applications: unité, intégration et tests de bout en boutTest C # .NET Applications: unité, intégration et tests de bout en boutApr 09, 2025 am 12:04 AM

Les stratégies de test pour les applications C # .NET comprennent les tests unitaires, les tests d'intégration et les tests de bout en bout. 1. Le test unitaire garantit que l'unité minimale du code fonctionne indépendamment, en utilisant le cadre MSTEST, NUnit ou Xunit. 2. Les tests intégrés vérifient les fonctions de plusieurs unités combinées et des données simulées couramment utilisées et des services externes. 3. Les tests de bout en bout simulent le processus de fonctionnement complet de l'utilisateur et le sélénium est généralement utilisé pour les tests automatisés.

See all articles

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques moisBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
1 Il y a quelques moisBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
1 Il y a quelques moisBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Commandes de chat et comment les utiliser
1 Il y a quelques moisBy尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Version crackée d'EditPlus en chinois

Version crackée d'EditPlus en chinois

Petite taille, coloration syntaxique, ne prend pas en charge la fonction d'invite de code

Version Mac de WebStorm

Version Mac de WebStorm

Outils de développement JavaScript utiles

Navigateur d'examen sécurisé

Navigateur d'examen sécurisé

Safe Exam Browser est un environnement de navigation sécurisé permettant de passer des examens en ligne en toute sécurité. Ce logiciel transforme n'importe quel ordinateur en poste de travail sécurisé. Il contrôle l'accès à n'importe quel utilitaire et empêche les étudiants d'utiliser des ressources non autorisées.

SublimeText3 version anglaise

SublimeText3 version anglaise

Recommandé : version Win, prend en charge les invites de code !

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP