Static - thread safe

0

Czy metoda statyczna, która nie ma efektów ubocznych oraz jest bezstanowa, do której przekazuje instancje obiektu, czyli kopiuje referencje, jest bezpieczna tak długo, jak inny wątek nie może zmienić stanu owej instancji przekazanej przez parametr metody?

Metoda wykonuje prosty algorytm w pętli, który nie zmienia stanu obiektu przekazanego przez parametr, jest to prosta fabryka.

1

Wydaje się, że tak. Dopóki nie pokażesz kodu, dopóty pewności nie będzie.

0

Podajesz sprzecznie dane:

  • "... tak długo, jak inny wątek nie może zmienić stanu owej instancji ..."
  • "... który nie zmienia stanu obiektu przekazanego przez parametr ..."
0

Zablokuj ją, dla pewności. Jeśli się mylę, niech mnie ktoś poprawi:


object methodLocker = new object();

public static void MyStaticMethod(MyClass obj)
{
    lock(methodLocker)
    {
       //tutaj całe ciało
    }
}
0
_13th_Dragon napisał(a):

Podajesz sprzecznie dane:

  • "... tak długo, jak inny wątek nie może zmienić stanu owej instancji ..."
  • "... który nie zmienia stanu obiektu przekazanego przez parametr ..."

Jeśli ja przekaże tę instancję obiektu mutowalnego do 5 różnych metod współbieżnie które nie przekazują instancji jako readonly to pewnie zdąży się coś złego.

Kolega tłumaczył mi to tak, że do metody statycznej mogą się dostać na raz dwa wątki i wykonać tego samego if'a co zmieni wynik jednego "wątka" albo drugiego "wątka" na nieprawidłowy, lub obydwa "wątki" stworzą naraz tą samą instancje.
Brzmiało to tak, jak by pracował na komputerze kwantowym, lecz wydawał się bardzo przekonujący.

1

To brzmi jak opis naiwnej implementacji singletona przez double checked lock, gdzie obiekt nie jest w pełni skonstruowany, ale referencja już jest przypisana do zmiennej. Trudno wyczuć, o co dokładnie chodziło koledze.

0
Jaro123 napisał(a):

Brzmiało to tak, jak by pracował na komputerze kwantowym, lecz wydawał się bardzo przekonujący.

Nie ma to nic a nic wspólnego z komputerem kwantowym.
Musisz zrozumieć jedno podstawowe zagadnienie, jeżeli mamy do czynienia z kilkoma wątkami to nie znamy momentu przełączenia się z jednego na drugi.
Więc może to być po np porównaniu przełączamy się zaś jak wchodzimy wewnątrz bloku tego if'a to już warunek nie jest prawdą.

0

@_13th_Dragon Przestań mi wsadzać do ust to, czego nie powiedziałem...
Poza tym, co to ma wspólnego z opisanym przeze mnie problemem?

Tak jak @Afish powiedział problem pojawi się kiedy mówimy np o singletonie bez locka.

Jeśli ktoś się ze mną nie zgadza, to niech napisze test, który to udowodni, ja napisałem coś takiego:

 class Program
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 1000; i++)
            {
                Console.WriteLine("Test Start");
                Parallel.Invoke(() =>
                {
                    var numbers = new Numbers(2, 2);
                    var sum = SumOfNumbers(numbers);

                    if (sum != 4)
                        throw new Exception("WTF....?");

                }, () =>
                {
                    var numbers = new Numbers(5, 5);
                    var sum = SumOfNumbers(numbers);

                    if (sum != 10)
                        throw new Exception("WTF....?");

                }, () =>
                {
                    var numbers = new Numbers(1, 1);
                    var sum = SumOfNumbers(numbers);

                    if (sum != 2)
                        throw new Exception("WTF....?");

                });
                Console.WriteLine("Test end");
            }
            Console.ReadLine();
        }

        public static int SumOfNumbers(Numbers numbers)
        {
            int sum = 0;

            if (numbers.NumberOne == 2 && numbers.NumberTwo == 2)
                sum = 4;

            if (numbers.NumberOne == 5 && numbers.NumberTwo == 5)
                sum = 10;

            if (numbers.NumberOne == 1 && numbers.NumberTwo == 1)
                sum = 2;

            return sum;
        }
    }

    public class Numbers
    {
        public Numbers(int numberOne, int NumberTwo)
        {
            NumberOne = numberOne;
            this.NumberTwo = NumberTwo;
        }

        public int NumberOne { get; }
        public int NumberTwo { get; }
    }

Potem jeszcze tak:

 static void Main(string[] args)
        {
            Parallel.For(0, 10000, i =>
            {
                Console.WriteLine("Test Start " + i);

                var numbers = new Numbers(2, 2);
                var sum = SumOfNumbers(numbers);

                if (sum != 4)
                    throw new Exception("WTF....?");

                var numbers2 = new Numbers(5, 5);
                var sum2 = SumOfNumbers(numbers2);

                if (sum2 != 10)
                    throw new Exception("WTF....?");

                var numbers3 = new Numbers(1, 1);
                var sum3 = SumOfNumbers(numbers3);

                if (sum3 != 2)
                    throw new Exception("WTF....?");

                Console.WriteLine("Test end");
            });
            Console.ReadLine();
        }
0
Jaro123 napisał(a):

@_13th_Dragon Przestań mi wsadzać do ust to, czego nie powiedziałem...

Ja zacytowałem. Zmieniłeś treść posta kilka razy aby się powymądrzać?

0
_13th_Dragon napisał(a):
Jaro123 napisał(a):

@_13th_Dragon Przestań mi wsadzać do ust to, czego nie powiedziałem...

Ja zacytowałem. Zmieniłeś treść posta kilka razy aby się powymądrzać?

Nie zmieniałem kontekstu wypowiedzi dodałem, brakujące przecinki. Pisz na temat albo się w ogóle nie odzywaj.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0