Is the next stream of objects safe?

Is the next stream of objects safe? I will make one instance and use it using two or more threads, is this a good way to get closer to this?

public class ASyncBuffer<T> { readonly object _locker = new object(); private T _value; private bool _dirty; public T GetValue() { lock (_locker) { _dirty = false; return _value; } } public void SetValue(T value) { lock (_locker) { _dirty = true; _value = value; } } public bool Dirty { get { lock (_locker) { return _dirty; } } } } 
+4
source share
5 answers

The object itself is thread safe, but make sure you consider using it as well. For example, if your use looks like this:

 if ( buffer.Dirty ) { var obj = buffer.GetValue(); } 

This usage is not thread safe, as the Dirty value can change between when you check it and when you really get the value.

To avoid this problem (and minimize the use of locking), you would like to use it like this:

 if ( buffer.Dirty ) { lock(buffer) { if ( buffer.Dirty ) { var obj = buffer.GetValue(); } } } 
+7
source

In short: no.

Once you give up ownership of the value, you can absolutely no guarantee what will happen. This becomes especially more pronounced when you rely on _value to have a specific value (not a pun) in something like an if-statement. When this happens, all you guarantee is that _value will not be in some partial write state when reading it.

The same is true for a dirty flag ... frankly it is even more pronounced with a dirty flag.

Consider this case:

 Thread 1 calls ASyncBuffer.SetValue(someValue) // sets the dirty flag to true Thread 1 checks ASyncBuffer.Dirty // should be true Thread 2 calls ASyncBuffer.GetValue() // sets the flag to false Thread 1 calls ASyncBuffer.GetValue() // you expect the dirty flag to be true, but it not 

In this sense, it is not protected by the flow.

+1
source

YES, but only when accessing the property itself, as soon as the property is used / assigned, it depends on the object being processed in order to process its internal state controlled by a thread-safe way.

0
source

Yes, but it may not be used.

I assume that you want to get the value if and only if it is "dirty" (since it is cleared with each extraction, so I do not see the value in the reverse order). Therefore, you must:

 if(buff.Dirty) { T val = buff.GetValue(); //operations on val. } 

However, if another thread calls GetValue() at the same time, then Dirty now false.

Therefore, its use is safe for only one reader thread (in this case, several writer threads are fine, since they only change Dirty in the opposite direction).

If you can have multiple readers, consider adding something like:

 public bool GetIfDirty(out T value) { lock (_locker) { if(!_dirty) { value = default(T); return false; } _dirty = false; value = _value; return true; } } 

Then you can both check Dirty and get the value, if you want, in the same stream operation.

0
source

AFAIK is not a thread protected program. Your getter and setter will have different locks. See thread for more details.

-3
source

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


All Articles