Tout programme où plus d'un thread n'accède à aucun aspect mutable de l'état du programme sera trivialement sûr pour les threads, car chaque thread peut également être son propre programme distinct. Cependant, le multi-threading utile nécessite généralement une interaction entre les threads, ce qui implique l'existence d'un état partagé mutable.
La clé d'un multithreading sûr et efficace est d'incorporer la mutabilité au «niveau de conception» approprié. Idéalement, chaque aspect de l'état du programme devrait être représentable par une référence immuable (*), mutable, à un objet dont l'état observable est immuable. Un seul thread à la fois peut essayer de changer l'état représenté par une référence mutable particulière. Le multi-threading efficace nécessite que la "couche mutable" dans l'état d'un programme soit suffisamment basse pour que différents threads puissent en utiliser différentes parties. Par exemple, si on a une structure de données AllCustomers
immuable et que deux threads tentent simultanément de changer de clients différents, chacun génère une version de la structure de données AllCustomers
qui inclut ses propres changements, mais pas celui de l'autre thread. Pas bien. Si AllCustomers
était un tableau mutable de CustomerState
objets, cependant, il serait possible pour un thread de travailler sur AllCustomers[4]
tandis qu'un autre travaillait sur AllCustomers[9]
, sans interférence. (*) Le chemin enraciné doit exister lorsque l'aspect de l'état devient pertinent et ne doit pas changer tant que l'accès est pertinent. Par exemple, on pourrait concevoir un AddOnlyList<thing>
qui contient un thing[][]
appelé Arr
qui a été initialisé à la taille 32. Lorsque la première chose est ajoutée, Arr[0]
serait initialisé, en utilisant CompareExchange
, à un tableau de 16 thing
. Les 15 prochaines choses iraient dans ce tableau. Lorsque la 17ème chose est ajoutée, Arr[1]
serait initialisé en utilisant CompareExchange
dans un tableau de taille 32 (qui contiendrait le nouvel élément et les 31 éléments après). Lorsque la 49ème chose est ajoutée, Arr[2]
sera initialisé pour 64 articles. Notez que tandis que thing
lui-même et les tableaux qu'il contient ne seraient pas totalement immuables, seul le premier accès à un élément serait écrit, et une fois que Arr[x][y]
contiendra une référence à quelque chose, il continuera à le faire tant que Arr
existe.
Un exemple de quoi? –
@Erick Robertson - Un exemple qui résout tous les problèmes! :) – willcodejavaforfood
@willcodejavaforfood - Apprécierait si peut fournir cet exemple. Merci! –