Reli Herlihy e Wing muitas vezes nos últimos 15 anos. É uma leitura muito difícil. E isso é lamentável, porque, embora existam algumas sutilezas nas bordas, a ideia básica é realmente bastante razoável.
Resumindo: linearizabilidade é como serializabilidade, mas com o requisito adicional de que a serialização respeite restrições adicionais de pedidos entre as transações. O objetivo é permitir que você raciocine rigorosamente sobre uma estrutura de dados atômicos individuais, em vez de ter que raciocinar sobre todo o sistema de uma só vez.
A linearidade também é fácil de obter: basta associar um mutex ao objeto que você deseja linearizar. Toda transação nesse objeto começa bloqueando o mutex e termina desbloqueando o mutex.
Aqui estão as definições que vou usar:
Um sistema é serializável se um determinado conjunto de transações for fornecido sobre um conjunto de dados, qualquer resultado da execução das transações é o mesmo que se as transações fossem executadas em alguma ordem seqüencial e as operações em cada transação estiverem contidas na transação na ordem especificado pelo código da transação.
A serialização permite a aparência de intercalação de operações entre transações diferentes e exige que a ordem escolhida das transações satisfaça a causalidade (se a transação A gravar o valor x, e a transação B ler o valor x que A escreveu, a transação A deverá preceder a transação B em a ordem serial escolhida.) Mas não diz nada sobre outras restrições à ordem das transações (em particular, nada diz sobre processos e a ordem na qual os processos percebem eventos).
Há outra ideia relacionada que adiciona restrições à ordem na qual os processos executam operações (mas não fala sobre transações apenas operações de leitura / gravação individuais):
Um sistema é sequencialmente consistente se o resultado de qualquer execução for o mesmo que se as operações de todos os processos fossem executadas em alguma ordem seqüencial, e as operações de cada processo individual aparecerem nessa sequência na ordem especificada por seu programa. ( Lamport, "Como criar um computador multiprocessador que execute corretamente programas multiprocessos", IEEE T Comp 28: 9 (690-691), 1979 ).
Implícito na definição de consistência sequencial é que só aceitamos ordens sequenciais em que, para cada local da memória (objeto), a ordem sequencial induzida de operações obedece à regra de que o valor retornado por cada operação de leitura para o local x
deve ter o mesmo valor que foi escrito por a operação de gravação imediatamente anterior ao local x
na ordem sequencial.
A linearidade tem as boas intenções de (a) combinar a noção de transações (da serialização) com a noção de que os processos esperam que as operações que eles emitem sejam concluídas em ordem (de consistência sequencial) e (b) restringir os critérios de correção para falar sobre cada objeto isolado, em vez de forçá-lo a raciocinar sobre o sistema como um todo. (Eu gostaria de poder dizer que a implementação do meu objeto está correta, mesmo em um sistema em que existem outros objetos que não são linearizáveis.) Acredito que Herlihy e Wing possam estar tentando definir rigorosamente um monitor .
A parte (a) é "fácil": um requisito sequencial semelhante à consistência seria que as transações no objeto emitido por cada processo apareçam na sequência resultante na ordem especificada pelo programa. Um requisito semelhante à serialização seria que as transações no objeto sejam todas mutuamente exclusivas (podem ser serializadas).
A complexidade vem do objetivo (b) (poder falar sobre cada objeto independentemente de todos os outros).
Em um sistema com vários objetos, é possível que as operações no objeto B imponham restrições na ordem em que acreditamos que as operações foram invocadas no objeto A. Se estivermos analisando todo o histórico do sistema, ficaremos restritos a determinadas ordens sequenciais, e precisará rejeitar os outros. Mas queríamos um critério de correção que pudéssemos usar isoladamente (raciocínio exatamente sobre o que acontece com o objeto A sem apelar para o histórico global do sistema).
Por exemplo: suponha que eu esteja tentando argumentar sobre a correção do objeto A, que é uma fila, suponha que o objeto B seja um local de memória e suponha que eu tenha os seguintes históricos de execução: Thread 1: A.enqueue (x), A. desenfileirar () (retorna y). Thread 2: A.enqueue (y), A.dequeue () (retorna x). Existe uma intercalação de eventos que permitiria que essa implementação da fila estivesse correta? Sim:
Thread 1 Thread 2
A.enqueue(x) ...
... A.enqueue(y)
... A.dequeue() (returns x)
A.dequeue(y) (returns y) ...
Mas agora e se o histórico ( incluindo o objeto B ) for: B começa com o valor 0. Thread 1: A.enqueue (x), A.dequeue () (retorna y), B.write (1). Tópico 2: B.read () (retorna 1) A.enqueue (y), A.dequeue () (retorna x).
Thread 1 Thread 2
A.enqueue(x) ...
A.dequeue() (returns y) ... (uh oh!)
B.write(1) ...
... B.read() (returns 1)
... A.enqueue(y)
... A.dequeue() (returns x)
Agora, gostaríamos que nossa definição de "correção" diga que esse histórico indica que nossa implementação de A é incorreta ou nossa implementação de B é incorreta, porque não há serialização que "faça sentido" (o Tópico 2 precisa ler um valor de B que ainda não foi gravado ou o Thread 1 precisa retirar da fila um valor de A que ainda não foi enfileirado.) Portanto, enquanto nossa serialização original das transações em A parecia razoável, se nossa implementação permite uma história como a segunda, então está claramente incorreta.
Portanto, as restrições adicionadas pela linearização são bastante razoáveis (e necessárias mesmo para estruturas de dados simples, como filas FIFO.) São coisas como: "sua implementação deve proibir dequeue () um valor que não será enfileirado () até algum tempo no futuro." A linearidade é bastante fácil (e natural) de alcançar: basta associar um mutex ao seu objeto, e cada transação começa bloqueando e termina desbloqueando. O raciocínio sobre linearização começa a ficar complicado quando você está tentando implementar sua atomicidade com técnicas sem bloqueio, sem bloqueio ou sem espera, em vez de simples mutexes.
Se você está interessado em algumas dicas para a literatura, encontrei o seguinte (embora eu ache que a discussão sobre "tempo real" seja um dos truques que tornam a linearização mais difícil do que precisa) https: // stackoverflow.com/questions/4179587/difference-between-linearizability-and-serializability