Existem regras / diretrizes gerais para o que torna um método seguro para threads? Entendo que provavelmente há um milhão de situações pontuais, mas e em geral? Isso é simples?
- Se um método acessa apenas variáveis locais, é seguro para threads.
É isso? Isso também se aplica a métodos estáticos?
Uma resposta, fornecida por @Cybis, foi:
Variáveis locais não podem ser compartilhadas entre os segmentos, porque cada segmento recebe sua própria pilha.
Esse também é o caso dos métodos estáticos?
Se um método é passado para um objeto de referência, isso quebra a segurança do encadeamento? Eu fiz algumas pesquisas e existem muitos casos sobre certos casos, mas eu esperava poder definir, usando apenas algumas regras, diretrizes a seguir para garantir que um método seja seguro para threads.
Então, acho que minha pergunta final é: "Existe uma pequena lista de regras que definem um método seguro para threads? Em caso afirmativo, quais são elas?"
EDIT
Muitos pontos positivos foram feitos aqui. Penso que a resposta real para esta pergunta é: "Não existem regras simples para garantir a segurança do thread". Legal. Bem. Mas, em geral , acho que a resposta aceita fornece um resumo breve e bom. Sempre há exceções. Que assim seja. Eu posso viver com isso.
fonte
Respostas:
Se um método (instância ou estático) referenciar apenas variáveis com escopo dentro desse método, ele será seguro para threads, pois cada thread possui sua própria pilha:
Nesse caso, vários threads poderiam chamar
ThreadSafeMethod
simultaneamente sem problemas.Isso também é verdade se o método chamar outro método de classe que faça referência apenas a variáveis com escopo local:
Se um método acessar propriedades ou campos (estado do objeto) (instância ou estática), será necessário usar bloqueios para garantir que os valores não sejam modificados por um encadeamento diferente.
Você deve estar ciente de que quaisquer parâmetros passados para o método que não sejam uma estrutura ou imutáveis podem ser alterados por outro encadeamento fora do escopo do método.
Para garantir a simultaneidade adequada, você precisa usar o bloqueio.
para obter mais informações, consulte a referência de bloqueio C # reference e ReadWriterLockSlim .
O bloqueio é útil principalmente para fornecer uma funcionalidade de cada vez;
ReadWriterLockSlim
é útil se você precisar de vários leitores e escritores únicos.fonte
private string someValue;
não éstatic
assim que cada instância receberá uma cópia separada dessa variável. Então, você pode explicar como isso não é seguro para threads?Thing
classe acessada por vários segmentosAbsolutamente não. Você pode escrever um programa com apenas uma única variável local acessada a partir de um único thread que, no entanto, não é seguro:
https://stackoverflow.com/a/8883117/88656
Absolutamente não.
Absolutamente não. A característica distintiva de uma variável local é que ela só é visível no escopo local , e não que seja alocada no pool temporário . É perfeitamente legal e possível acessar a mesma variável local a partir de dois threads diferentes. Você pode fazer isso usando métodos anônimos, lambdas, blocos de iteradores ou métodos assíncronos.
Absolutamente não.
Talvez.
Você terá que aprender a viver com decepção. Este é um assunto muito difícil.
Não. Como você viu no meu exemplo anterior, um método vazio pode não ser seguro para threads . Você também pode perguntar "existe uma pequena lista de regras que garantem que um método esteja correto ". Não, não há. A segurança da linha nada mais é do que um tipo de correção extremamente complicado.
Além disso, o fato de você estar fazendo a pergunta indica seu mal-entendido fundamental sobre segurança de threads. A segurança do thread é uma propriedade global e não local de um programa. A razão pela qual é tão difícil acertar é porque você deve ter um conhecimento completo do comportamento de segmentação de todo o programa para garantir sua segurança.
Novamente, veja o meu exemplo: todo método é trivial . É a maneira como os métodos interagem entre si em um nível "global" que torna o programa em conflito. Você não pode olhar para todos os métodos e selecioná-lo como "seguro" e esperar que todo o programa seja seguro, assim como não é possível concluir que, porque sua casa é feita de tijolos 100% não vazados, a casa também é não oco. O vazio de uma casa é uma propriedade global de toda a coisa, não um agregado das propriedades de suas partes.
fonte
class C { public static Func<int> getter; public static Action<int> setter; public static void M() { int x = 0; getter = ()=>x; setter = y=>{x=y;};} }
Chame M () e chame C.getter e C.setter em dois threads diferentes. A variável local agora pode ser gravada e lida em dois threads diferentes, mesmo que seja local. Novamente: a característica definidora de uma variável local é que ela é local , não que esteja na pilha do encadeamento .Não existe uma regra rígida e rápida.
Aqui estão algumas regras para tornar o encadeamento de código seguro no .NET e por que essas regras não são boas:
lock
uma coisa comum. Todos os bloqueios devem ser feitos na mesma ordem. Isso tornará o encadeamento de código seguro, mas será incrivelmente lento, e você também não poderá usar vários encadeamentos.Não existe uma regra que torne o encadeamento de código seguro, a única coisa que você pode fazer é garantir que seu código funcione, não importa quantas vezes ele esteja sendo executado ativamente, cada encadeamento pode ser interrompido a qualquer momento, com cada encadeamento em seu próprio estado / local e isso para cada função (estática ou não) que está acessando objetos comuns.
fonte
Ele deve ser sincronizado, usando um bloqueio de objeto, sem estado ou imutável.
link: http://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html
fonte