2010-02-06 3 views
11

Cela peut sembler une question stupide, mais si l'on verrouille une ressource dans une application multi-thread, alors l'opération qui se passe sur la ressource, est-ce fait atomiquement? I.E.: le processeur peut-il être interrompu ou un changement de contexte peut-il se produire alors que cette ressource est verrouillée? Si c'est le cas, rien d'autre ne peut accéder à cette ressource tant qu'elle n'est pas planifiée pour terminer son processus. Cela ressemble à une opération coûteuse.Est-ce qu'un verrou (filetage) atomique?

Répondre

16

Le processeur peut très certainement passer à un autre thread, oui. En effet, dans la plupart des ordinateurs modernes, plusieurs threads peuvent fonctionner simultanément. Le verrouillage s'assure juste qu'aucun autre thread ne peut acquérir le même verrou, donc vous pouvez vous assurer qu'une opération sur cette ressource est atomique en termes de cette ressource. Le code utilisant d'autres ressources peut fonctionner de manière totalement indépendante.

Vous devez généralement verrouiller pour les opérations courtes dans la mesure du possible. Vous pouvez également choisir la granularité des verrous ... par exemple, si vous avez deux variables indépendantes dans un objet partagé, pouvez utiliser deux verrous distincts pour protéger l'accès à ces variables. Cela permettra potentiellement une meilleure concomitance - mais en même temps, plus de verrous signifie plus de complexité et plus de potentiel d'interblocage. Il y a toujours un équilibre quand il s'agit de concurrence.

+0

Alors, si un autre thread attend cette ressource, il doit continuer à attendre? –

+1

@Tony - oui, il bloquera attendre d'acquérir le verrou jusqu'à ce qu'il soit libéré par le premier thread – Paolo

+4

Eh bien, bien sûr. C'est ce que l'on veut d'une serrure. – botismarius

7

Vous avez tout à fait raison. C'est l'une des raisons pour lesquelles il est si important de verrouiller pendant une courte période de temps. Cependant, ce n'est pas aussi grave que ça en a l'air, car aucun autre thread qui attend sur le verrou ne sera programmé tant que le thread qui le déverrouillera ne l'aura pas libéré.

+1

"C'est une des raisons pour lesquelles il est si important de verrouiller pendant une courte période" ?????? MAIS une section verrouillée d'un fil peut être DEFINITIVEMENT interrompue par un autre fil. Pour être précis, par tout fil qui n'utilise pas le même verrou. – ulrichb

2

Oui, un changement de contexte peut certainement se produire. C'est la raison pour laquelle, lors de l'accès à une ressource partagée, il est important de la verrouiller à partir d'un autre thread. Lorsque le fil A a le verrou, le fil B ne peut pas accéder au code verrouillé.

Par exemple, si deux threads exécutent le code suivant:

1. lock(l); 
2. -- change shared resource S here -- 
3. unlock(l); 

Un changement de contexte peut se produire après l'étape 1, mais l'autre thread ne peut pas tenir le verrou à ce moment-là, et, par conséquent, ne peut pas changer la ressource partagée . Si l'accès à la ressource partagée sur l'un des threads se fait sans verrou - de mauvaises choses peuvent arriver!

En ce qui concerne le gaspillage, oui, c'est une méthode inutile. C'est pourquoi il existe des méthodes qui tentent d'éviter complètement les verrous. Ces méthodes sont appelées lock-free, et certaines d'entre elles sont basées sur des services de verrouillage puissants tels que CAS (Compare-And-Swap) ou autres.

0

Non, ce n'est pas vraiment cher. Il n'y a généralement que deux possibilités:

1) Le système a d'autres choses qu'il peut faire: Dans ce cas, le système fait toujours un travail utile avec tous les cœurs disponibles. 2) Le système n'a rien d'autre à faire: Dans ce cas, le thread qui détient le verrou sera planifié. Un système sensé ne laissera pas un noyau inutilisé alors qu'il existe un thread prêt à l'emploi qui n'est pas planifié.

Alors, comment cela peut-il être cher? Si le système n'a rien d'autre à faire, cela ne nécessite pas l'acquisition de ce verrou (ou pas assez d'autres choses pour occuper tous les cœurs) et le thread qui détient le verrou est et non prêt à l'emploi.C'est donc le cas que vous devez éviter, et le changement de contexte ou le problème de pré-emption n'a pas d'importance (puisque le thread serait prêt à fonctionner).