É muito simples. Os bloqueios de leitura também são conhecidos como bloqueios compartilhados porque mais de um processo pode ler ao mesmo tempo. O objetivo de um bloqueio de leitura é evitar a aquisição de um bloqueio de gravação por outro processo. Por outro lado, um bloqueio de gravação inibe todas as outras operações enquanto uma operação de gravação é concluída, por isso é descrita como exclusiva.
Portanto, um bloqueio de leitura diz "você pode ler agora, mas se quiser escrever, terá que esperar", enquanto um bloqueio de gravação diz "você terá que esperar".
Sei que você está pesquisando para apoiar seus estudos, mas não consigo resistir à vontade de dar uma palestra.
O uso incompetente de travamento é a principal causa de dores de cabeça de desempenho. O uso de um sistema de bloqueio que diferencia os bloqueios de leitura e gravação é um bom começo, mas o design cuidadoso pode, às vezes, eliminar grande parte da necessidade de bloqueio. Por exemplo, o estado da sessão nunca deve ser mantido em uma coleção global por elemento de estado.
Eu realmente vi isso ser feito. É um design atroz, causando boxe e uma mudança em uma coleção para cada última mudança no estado da sessão, acarretando um bloqueio de gravação prolongado. As despesas gerais estavam prejudicando, reduzindo efetivamente o servidor a um comportamento de thread único.
Simplesmente agregar todo o estado da sessão em uma estrutura foi uma grande melhoria. Mudanças no estado da sessão simplesmente mudaram os valores dos membros de uma estrutura de estado da sessão. Como nenhuma outra sessão teve ocasião ou mesmo oportunidade de fazer referência direta ao estado de uma sessão, a única coleção sendo atualizada foi a lista de sessões. Como resultado, o bloqueio era completamente desnecessário durante uma sessão, apenas no início e no final, e a taxa de transferência aumentou por um fator de 3.000.
O outro cenário de bloqueio comum são recursos compartilhados entre threads de um aplicativo de usuário. A maioria das estruturas modernas trata disso usando mensagens em vez de bloqueios; quando você "faz a transição para o thread de interface do usuário", está na verdade enfileirando uma mensagem contendo um ponteiro de função e alguns parâmetros (ou um delegado e um quadro de pilha dependendo da implementação).