Multithreaded variable access

This question haunts me: in a multi-threaded / multi-processor environment - do I need to use explicit locks to synchronize access to shared variables?

Here is the scenario: I have a global variable pointing to a shared object. When an object instance is created, a reference to it is placed in a variable and becomes available to other threads / processors.

The object itself is unchanged - after its creation, it never changes, since these several threads can access it without additional synchronization.

From time to time I need to update the object. I do this by creating a new instance of the object on the side, and then put the link to the new object in a global variable.

So here is the question: can I consider replacing the reference to an atomic operation. In other words, does a variable always have a valid reference to my object - either old or new?

+3
source share
8 answers

Do I need to use explicit locks to synchronize access to shared variables?

necessary? No. A good idea? Yes. Low-block methods are very difficult to get right and rarely justified. Remember that blocking is slow when disputed; if your locks are disputed, fix the problem that causes them to be disputed, rather than moving to a low-lock solution.

- ​​ , .

.

. , , .

, : . , - , ?

. # , . - . , , , . , , , . , . , , . Atomity , , , .

: , . , . , , , , , , ..

+10

- , . # Language Specification, 12.5 .

, volatile ( 17.4.3). , . volatile, Threading in #.

+2

, . , , .

, " " ( ), volatile. : volatile #.

+1

.NET. , . , . . , , .

, , . .

+1

.

, . . , , .

internal static class EvilSingleton
{
    public static int[] FavoriteNumbers;
}

internal class FavoriteNumberView
{
    private ListBox selectNumberListBox;

    private void LoadNumberListTheWrongWay()
    {
        Debug.Assert(selectNumberListBox != null);

        selectNumberListBox.Clear();

        if (EvilSingleton.FavoriteNumbers == null)
            return;

        // This code is just asking for null reference and array bounds exceptions!!!
        for (int index = 0; index < EvilSingleton.FavoriteNumbers.Length; index++)
            selectNumberListBox.Add(EvilSingleton.FavoriteNumbers[index].ToString());
    }

    private void LoadNumberListTheRightWay()
    {
        // Store the global reference in a local variable, and 
        // only use the local reference from now on.
        int[] favoriteNumbers = EvilSingleton.FavoriteNumbers;

        Debug.Assert(selectNumberListBox != null);

        selectNumberListBox.Clear();

        if (favoriteNumbers == null)
            return;

        // The local reference will never be null, and the array bounds will always be
        // correct. In fact, the optimizer can remove most bounds checking from this 
        // loop, since it knows the array length will not change.
        for (int index = 0; index < favoriteNumbers.Length; index++)
            selectNumberListBox.Add(favoriteNumbers[index].ToString());
     }
}
+1

, . - LockWriter lock ( ReaderWriterLockSlim) - , . , , .

. , .

0

Are you using .NET 4.0? If so, you can take a look at System.Collections.Concurrent Namespace . If you do not need an ordered list, you can use ConcurrentBag .

0
source

Source: https://habr.com/ru/post/1781465/


All Articles