When implementing streaming security or a list, a lock is required before returning Count?

When implementing a secure thread or queue; this is required to lock the List.Count property before returning Count ie:

//... public int Count { lock (_syncObject) { return _list.Count; } } //... 

Do I need to lock because of the original variable _list.Count, possibly a mutable variable?

Thanks for the advanced.

+4
source share
3 answers

It depends.

Now, theoretically, since the underlying value is not thread safe, pretty much everything can go wrong because the implementation does something. In practice, however, it is reading from a 32-bit variable and therefore guaranteed to be atomic. Therefore, it may be obsolete, but it will be a real black value, and not the garbage caused by reading half the value before the change, and the other half after it.

So the question is, does the question of stillness matter? Probably no. The more you can come to terms with accuracy, the better for performance (because the more you can come to terms with this, the less you need to do so that you don't have anything outdated). For instance. if you put an invoice into the user interface and the collection changes quickly, then just the time it takes for a person to read the number and process it in his own brain will be sufficient to make it obsolete anyway, and therefore stale.

If, however, you had to make sure that the operation was reasonable before it was undertaken, then this delay will cause problems.

However, this constancy will happen anyway, because in the interval between your blocked (and guaranteed fresh) reading and the operation performed, it becomes possible to change the collection, so you have a race condition, even when the castle.

Therefore, if freshness is important, you will have to block at a higher level. In this case, blocking the lower level is just a waste. Therefore, you can possibly do without this at this moment.

The important thing is that even with a class that is thread safe in every way, the best that can guarantee is that every operation will be fresh (although even this may not be guaranteed, in fact, when more than one core is involved, the "fresh" starts become meaningless, since changes can occur that are close to truly simultaneous) and that each operation does not place the object in an invalid safe. You can still write non-threaded code with thread safe objects (indeed, a lot of non-thread objects consist of ints, strings and bools or objects, which in turn consist of them, and each of them is itself thread safe).

One thing that can be useful with mutable classes designed for multi-threaded use is the synchronized Try methods. For instance. To use the list as a stack, we need the following operations:

  • See if the pool is empty, report an error, if any.
  • Get the "upper" value.
  • Remove the upper value.

Even if we synchronize each of them separately, the code doing this will not be thread safe, because something can happen between each step. However, we can provide the Pop() method, which executes every three in one synchronized method. Similar approaches are also useful for loose classes (where different methods are used to ensure that the method either succeeds or does not work completely and does not damage the object).

+2
source

Yes, it is necessary, but basically it does not matter. Without blocking, you can read stale values ​​or even, depending on the internal work and type _list.Count, enter errors.

But note that using this Count property is problematic, any calling code cannot really rely on it:

 if (myStore.Count > 0) // this Count getter locks internally { var item = myStore.Dequeue(); // not safe, myStore could be empty } 

Thus, you should strive for a design in which the graph check and actions on it are combined:

 ItemType GetNullOrFirst() { lock (_syncObject) { if (_list.Count > 0) { .... } } } 

Additionally:

Do I need to lock because of the original variable _list.Count, possibly a mutable variable?

_list.Count not a variable, but a property. It cannot be labeled unstable. Regardless of whether it is thread safe, it depends on the property getter code, but it will usually be safe. But unreliable.

+5
source

No, you do not need to block, but the caller must otherwise something like this could happen

 count is n thread asks for count Count returns n another thread dequeues count is n - 1 thread asking for count sees count is n when count is actually n - 1 
+2
source

All Articles