Reading the transverse thread of a variable whose value is not considered important

In C #, there is a way to update a variable (without using a lock), where multiple threads can read a value, but a thread that updates the variable is not considered important.

I mean, if a thread updates this value, but other threads do not receive this updated value after a few minutes, then this is normal.

Is there such a way?

Many thanks

+1
source share
9 answers

The best option is to use ReaderWriterLockSlim (or ReaderWriterLock if you are not using .net 3.5). Hint: This tutorial should get started.

+4
source

If the updated value is not important for other threads, why is the variable shared between threads? Each thread can use its own copy.

I don’t understand this. Do you want to deliberately delay the reading of values, or do you mean that it doesn’t matter if other threads cannot immediately see the updated value?

In any case, if you want to atomically update a variable without locking, you should use Interlocked methods, but I'm not quite sure if this is what you need.

+4
source

It depends on what you are trying to do. You can check the volatile box, but it may not be useful. I'm not sure volatile will guarantee that increment is an atomic operation, for example. In other words, one of your increments (or other updates) may be "lost" (overwritten by another thread). You can use Interlocked.Increment for this .

Again, it really depends on what you are trying to do. In most cases, it is easiest to use a lock.

+4
source

It looks like it could be a circular way to re-create a caching mechanism. Have you looked at any of the many caching systems available for .NET?

+1
source

You can atomically update a variable without locking with Interlocked.CompareExchange until you succeed. This avoids the overhead of locking while ensuring consistency, this pseudocode should do this, sorry, I'm not too familiar with C #.

static void atomic_add(ref int ptr, int addend){ int previous = *ptr; while(1){ int observed = Interlocked.CompareExchange(ptr, previous+addend, previous); if(observed == previous){ break; }else{ previous = observed; } } } 

CompareExchange will replace the value in the first argument with the second argument if the value specified by the first argument is equal to the third argument and returns the value in memory in ptr when CompareExchange is called. If the value returned by the exchange of the exchange matches the previous value observed in ptr, then the value was successfully updated and the cycle is interrupted, otherwise the value in the pointer has changed since the last update of the last and previous, and we will try again.

From what I read, Interlocked.CompareExchange exists only for int32, floats and objects (although not sure if it will be completely blocked?). I suppose that this will work for wider values ​​on 64-bit platforms, but I have nothing to support it.

+1
source

Assuming some threads are updating your shared variable, if you are not using any kind of synchronization then your other threads are:

  • May or may not immediately read the updated value. If not, they will read it later.
  • Will have an inconsistent value (some will get a new value, others will have an updated value) for a short period of time

If these problems are not significant, and if your logic does not depend on the value of a common variable, then synchronization is not required. Just allow all threads access to the shared variable.

What are you trying to achieve? It will be helpful to get a better answer.

Edit:

As ShuggyCoUk points out, use this approach with caution. It relies on atomic reading and writing, which depends on the type of your shared variable. Excerpt from here :

Reading and writing the following data types are atomic: bool, char, byte, sbyte, short, ushort, uint, int, float and reference types. In addition, reading and writing an enumeration of types with a base type in the previous list is also atomic. Reads and writes about other types, including long, ulong, double and decimal, as as well as custom types, not guaranteed atomic.

+1
source

I would put the data in an immutable "class" (so this is a reference type).

If you want to update the value, you first create a new instance and then update the reference to it (this is an atomic operation).

Each stream of readers will receive a consistent old or sequential new value (depending on the point in time that it reads from the link). It is not possible to get intermediate results because the data class is immutable!

+1
source

You can take a look at System.Threading.AutoResetEvent or System.Threading.ManualResetEvent .

It allows you to trigger events on threads (value changed). ManualResetEvent might be more appropriate if you want to be lazy in updates ...

I'm not sure if you are looking at access control for the specified variable ... In this case, the synchronous method can do the trick:

 [MethodImpl(MethodImplOptions.Synchronized)] public void Foo() { // Do foo } 

You can also get a lock for the specified object when changing its value:

 lock(myObject) { myObject = new value; } 
0
source

Use .Net types that are atomic
It depends on which variable you are using. Some variables act atomically. Atomic recording means that the processor writes the entire variable in one go, or you can at least consider it that way. This means that no other thread sees a partially updated variable - which would be clearly bad! Variables that behave atomically will behave as you ask, without requiring locking.

Assignments to the reference types, bool, char, byte, sbyte, short, ushort, uint, int and float are atomic.

I got a list of atomic types here: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/a5a3c1b4-9f76-43d7-90a6-6572c59491fe

See C # specification section 5.5 here: http://download.microsoft.com/download/3/8/8/388e7205-bc10-4226-b2a8-75351c669b09/CSharp%20Language%20Specification.doc

0
source

All Articles