I want to run a cleanup task that might run for several seconds. Multiple threads could call this task but I want to run this task only once. All other invokations should just skip.
The following is my current implementation but I cannot imagine there is not a better solution in the .net framework resulting in less lines of code.
object taskLock;
bool isRunning;
void Task()
{
if (isRunning) return;
try
{
lock (taskLock)
{
if (isRunning) return;
isRunning = true;
}
// Perform the magic
}
finally
{
isRunning = false;
}
}
Yes, there is a better solution. You can use Interlocked.CompareExchange, the code becomes simpler and lock-free:
class Worker
{
private volatile int isRunning = 0;
public void DoWork()
{
if (isRunning == 0 && Interlocked.CompareExchange(ref isRunning, 1, 0) == 0)
{
try
{
DoTheMagic();
}
finally
{
isRunning = 0;
}
}
}
private void DoTheMagic()
{
// do something interesting
}
}
In this case Interlocked.CompareExchange does the following as an atomic operation (pseudo-code):
wasRunning = isRunning;
if isRunning = 0 then
isRunning = 1
end if
return wasRunning
From the MSDN documentation:
public static int CompareExchange(
ref int location1,
int value,
int comparand
)
If comparand and the value in location1 are equal, then value is
stored in location1. Otherwise, no operation is performed. The compare
and exchange operations are performed as an atomic operation. The
return value of CompareExchange is the original value in location1,
whether or not the exchange takes place
Related
I have a method which is been called every 1 hour. But sometimes the method operations are not been completed fully within one hour and the method is again been called which causes confusion. So I have to find out if the previous method is been completed. Which is the best solution for this problem?
// will be called for every one hour where the value will be repeated
// At sometimes it is possible for the same value to be called continually
for the next hour and at that time problem occurs
Void Method(int value)
{
If(value =0)
// Do some operations which may exceed one hour
Else If(value =1)
// Do some operation’s which may exceed one hour
.
.
.
}
Thanks,
One question would be what do you want to happen if the method is called while it is still running?
This code will just drop the 2nd call
private bool _running = false;
private readonly object _lock = new object();
void Method(int value)
{
lock (_lock)
{
if (_running)
{
return;
}
else
{
_running = true;
}
}
if (value == 0)
{
// Do some operations which may exceed one hour
}
else if (value == 1)
{
// Do some operation’s which may exceed one hour
}
_running = false;
}
A simple idea is to save the state in a class field, so that the method checks to see if it's free to do some work or not. This will mean that if you call the method and it's busy, the work won't happen for your call:
private static bool methodIsBusy = false;
private static void WaitAndWriteMessage(TimeSpan waitTime, string message)
{
// If we're busy, return right away
if (methodIsBusy) return;
// Let future calls know we're busy
methodIsBusy = true;
Thread.Sleep(waitTime);
Console.Write($"Method ran at: {DateTime.Now.ToString("hh:mm:ss")}. ");
Console.WriteLine(message);
// Allow future calls to run now
methodIsBusy = false;
}
Our test method:
private static void Main()
{
for(int i = 0; i < 3; i++)
{
Task.Run(() => WaitAndWriteMessage(TimeSpan.FromSeconds(5),
$"Method called at {DateTime.Now.ToString("hh:mm:ss")}."));
Thread.Sleep(1000);
}
Console.ReadKey();
GetKeyFromUser("\nDone!\nPress any key to exit...");
}
Output
(Only the first of the three messages was printed)
Another idea is to use a lock, which means that calls to the method will pile up if the method is busy. All calls will eventually get completed, but if every call is longer than the iteration time in which the method is called, it will get further and further behind:
private static object methodLocker = new object();
private static void WaitAndWriteMessage(TimeSpan waitTime, string message)
{
// Lock on a common object, so this call will wait
// until there are no locks before it can continue
lock (methodLocker)
{
Thread.Sleep(waitTime);
Console.Write($"Method ran at: {DateTime.Now.ToString("hh:mm:ss")}. ");
Console.WriteLine(message);
}
}
Our test method again:
private static void Main()
{
for(int i = 0; i < 3; i++)
{
Task.Run(() => WaitAndWriteMessage(TimeSpan.FromSeconds(5),
$"Method called at {DateTime.Now.ToString("hh:mm:ss")}."));
Thread.Sleep(1000);
}
Console.ReadKey();
}
Output
(Notice the difference between when the message was called and when it executed gets longer each time)
How can i lock a part of method in c# from another threads?
I mean if one of threads was here, then exit...
For example:
if(threads[0].WasHere)
{
return;
}
an effective way is with an interlocked exchange; by setting some token field to a non-default value during the work, the other threads can check this and exit. For example:
private int hazWorker; // = 0 - put this at the scope you want to protect
then:
// means: atomically set hazWorker to 1, but only if the old value was 0, and
// tell me what the old value was (and compare that result to 0)
if(Interlocked.CompareExchange(ref hazWorker, 1, 0) != 0) {
return; // someone else has the conch
}
try {
// your work here
} finally {
Interlocked.Exchange(ref hazWorker, 0); // set it back to default
}
You can use Monitor.TryEnter for this purpose.
if(!Monitor.TryEnter(someLock))
{
return;
}
try
{
//Critical region
}
finally
{
Monitor.Exit(someLock);
}
Or more reliable way to fight with Rude Thread aborts (suggested by marc in comments)
bool lockTaken = false;
try
{
Monitor.TryEnter(someLock, ref lockTaken);
if (lockTaken)
{
//Critical region
}
}
finally
{
if(lockTaken) Monitor.Exit(someLock);
}
Note that this doesn't checks for threads[0] still working, rather it checks whether any other thread is in Critical region. If so, it exits the method.
You can use a bool value - assign it "false" on default, and then the first of the threads sets it to "true". And then the piece of code could look like this:
if (!alreadyExecuted)
{
// ...
alreadyExecuted = true;
}
I would also put the code in a lock to make sure only one thread executes it at time (to deal with any possible race conditions), like below.
The lockVariable is a locker variable and it can be of any reference type, ex. object lockVariable = new object();
lock (lockVariable)
{
if (!alreadyExecuted)
{
// ...
alreadyExecuted = true;
}
}
I have the following class:
public class AtomicLong
{
private long initial;
private long value;
public AtomicLong(long value = 0)
{
this.initial = value;
this.value = value;
}
public class Handle : IDisposable
{
private AtomicLong source;
private long amount;
public Handle(AtomicLong source, long amount)
{
this.source = source;
this.amount = amount;
}
public void Dispose()
{
if (source == null)
return;
Interlocked.Add(ref source.value, amount);
source = null;
}
}
public Handle Claim(long amount)
{
if (amount > initial)
throw new ArgumentOutOfRangeException("amount", amount, "Must be no more than the initial amount.");
if (amount < 0)
throw new ArgumentOutOfRangeException("amount", amount, "Must be nonnegative.");
while (true)
{
var oldValue = Interlocked.Read(ref value);
var newValue = oldValue - amount;
if (newValue >= 0 &&
oldValue == Interlocked.CompareExchange(ref value, newValue, oldValue))
{
return new Handle(this, amount);
}
}
}
}
An example usage of this is that I can have a single AtomicLong unusedMemory which represents the current number of bytes of memory available to a set of workers. (It's not meant to be anywhere near exact - it's just a rough measure.) I then do this on a bunch of different worker threads:
while (true)
{
var unitOfWork = WaitForUnitOfWork();
long requiredMemory = unitOfWork.RequiredMemory;
using (var handle = unusedMemory.Claim(requiredMemory))
{
//wait until requireMemory can be claimed from unusedMemory
//do work with reserved memory, represented by handle
//when handle disposes, memory is released back to the unusedMemory
}
}
The problem with my AtomicLong class is that calls to Claim will busy-wait until they return. I'd like to fix this by using some kind of OS-level wait handle abstraction.
Can you suggest how I could go about doing that?
Motivation
Consider the following scenario:
unusedMemory starts with an initial value of 10GB (10 << 30)
100 worker threads
10 units of work, each taking 10GB and 1 minute to perform
first worker calls Claim(10 << 30) and it nearly-immediately returns
it begins doing work that will finish after 1 minute
some 9 other workers make an identical call to Claim(10 << 30) and do a "bad" busy wait for 1 minute
9 threads doing something like a while(true){/*do nothing*/} loop in the Claim method!
lots of needless CPU usage
the rest of the workers (90) do a "good" OS-level wait in the WaitForUnitOfWork() method
The important point: Claim is only "cheap" if the requested amount of memory is actually available to be claimed. If it isn't, busy-waiting happens until it is available.
Just to be entirely clear, in the Claim method, I'm pointing out the exact expression which makes all the difference (newValue >= 0):
while (true)
{
var oldValue = Interlocked.Read(ref value);
var newValue = oldValue - amount;
if (newValue >= 0 && // <--------------------------- THIS IS THE PROBLEM
oldValue == Interlocked.CompareExchange(ref value, newValue, oldValue))
{
return new Handle(this, amount);
}
}
The question is not about whether Interlocked.CompareExchange is going to be expensive - I'm aware it's cheap. The question is about how to deal with the busy-waiting that occurs in the case when the amount a caller wants to Claim is currently greater than the amount in the AtomicLong.
If you have a completely different approach to solving this kind of problem, or see some flaw in what I already have, I'd like to hear about that too!
You have several options.
For instance, you can create a smarter busy-wait, by putting the active thread to sleep for a given time interval, so it doesn't always check your condition, but it does it periodically.
Another solution is to create a custom event and wait for that event in your active thread, and you can define a custom event which will fulfill your task I believe.
You can read more about events here. You can read about custom event creation here.
Here's the solution I came up with:
Parameters
obj: the synchronization object used by Monitor
pollIterval: the rate at which calls will poll until a successful transaction attempt
value: the value being modified by the transaction
precondition: an optional condition that must be true at the start of the transaction
transform: the operation that changes the value
postcondition: an optional condition that must be true at the end of the transaction
Code
public static class AtomicHelper
{
public static void LongTransaction(
object obj,
TimeSpan pollInterval,
ref long value,
Func<long, bool> precondition,
Func<long, long> transform,
Func<long, bool> postcondition)
{
while (true)
{
var oldValue = Interlocked.Read(ref value);
if (precondition != null && !precondition(oldValue))
{
Monitor.Wait(obj, pollInterval);
continue;
}
var newValue = transform(oldValue);
if (postcondition != null && !postcondition(newValue))
{
Monitor.Wait(obj, pollInterval);
continue;
}
if (Interlocked.CompareExchange(ref value, newValue, oldValue) == oldValue)
{
Monitor.PulseAll(obj);
return;
}
}
}
}
Example Usage
long n = 10;
object obj = new object();
//On many different threads, run this concurrently:
AtomicHelper.LongTransaction(
obj,
TimeSpan.FromSeconds(1),
ref n,
null,
x => x - 1,
x => x >= 0);
Thread.Sleep(TimeSpan.FromSeconds(3));
AtomicHelper.LongTransaction(
obj,
TimeSpan.Zero,
ref n,
null,
x => x + 1,
null);
I have a class that talks to an external .exe. The class has a bunch of similar methods; they call a function of the .exe, wait for response, and then return true or false.
The response comes in the form of events that change the values of fields of this class.
Simplified code:
class Manager
{
private static bool connected = false;
public static bool Connect()
{
runtime.Connect();
int secondsWaited = 0;
while (!connected)
{
Thread.Sleep(1000);
if (secondsWaited++ == 10)
{
return false;
}
}
return true;
}
}
The other methods use the same call-wait-loop-return structure.
My goal is to make a single method to do this waiting for me, like so:
private static bool WaitReferenceEqualsValue<T>(ref T reference, T value)
{
int secondsWaited = 0;
while (!reference.Equals(value))
{
Thread.Sleep(1000);
if (secondsWaited++ == 10)
{
return false;
}
}
return true;
}
Then each method would do:
runtime.DoSomething();
return WaitReferenceEqualsValue<someType>(ref someField, someSuccessfulValue);
However, when I replace the wait-loop with this method call, the field "connected", even though passed in as a reference, always stays the same.
Any idea what's going on here, and how to get the desired functionality?
Thanks in advance.
EDIT:
public static bool Connect()
{
...
runtime.Connect();
// this code works
/*int secondsWaited = 0;
while (connected != true)
{
Thread.Sleep(1000);
if (secondsWaited++ == 10)
{
return false;
}
}*/
// this somehow blocks OnConnect from firing, so connected never gets set to true
lock (typeof(SkypeKitManager))
{
WaitReferenceEqualsValue<bool>(ref connected, true);
}
...
}
OnConnect:
private static void OnConnect(object sender, Events.OnConnectArgs e)
{
if (e != null && e.success)
{
lock (typeof(Manager))
{
connected = true;
}
}
}
You're not doing any synchronization on that field although you access it from multiple threads and one of them is writing. This is a race (no exception! this is a race even if it looks safe. It isn't safe.).
Probably the JIT enregistered it which is a common optimization. It just never gets read from memory, always from a register. Add synchronization (for example a lock, or Interlocked or Volatile methods).
Your usage of ref is correct.
The problem with your code is essentially compiler optimization. Fo optimization purpose compilers (or jits) necessarily take a pretty much single threaded view. The compiler/jit will then notice that you don't touch reference in your code at all, therefore it can move the comparison outside the loop. It is free to do so, since you basically create a race condition (no synchronization/atomic accesses).
Fixing it could either involve using synchronization mechanisms or add the volatile specifier to reference, thus telling the compiler/jit, that the variable can be changed from outside the method.
I need to implement simple function that is called from multiple threads. The logic of the function is simple - think of horse races - only the first horse can get golden medal once we have a winner the race is over.
class ConditionalOrderGroup
{
private volatile bool _locked = false;
private List<ConditionalOrder> _ConditionalOrderList = null;
public bool LockGroup(ConditionalOrder initiator)
{
// this is finishline - we need to let only the first one proceed
if (_locked)
return false;
else
{
_locked = true;
}
// this is what winner gets
foreach (ConditionalOrder order in _ConditionalOrderList)
{
\\ cancel other orders
}
return true;
}
}
I am not happy with
if (_locked)
return false;
else
{
_locked = true;
}
What if two orders can pass if check and proceed to else. How to rewrite this code
without using lock statement?
UPDATE
I mean my goal is not use any blocking method like lock statement.
You need a separate, private object and use the built-in locking:
private object padLock = new object(); // 1-to-1 with _ConditionalOrderList
if (Monitor.TryEnter(padLock))
{
try
{
// cancel other orders
return true;
}
finally
{
Monitor.Exit(padLock);
}
}
else
{
return false;
}
Use Interlocked class to change values of the variable in a thread safe way.
Expanding on what decyclone said about interlocked, this is exactly how you would do it:
const int LOCKED = 1;
const int UNLOCKED = 0;
volatile int lockState = UNLOCKED;
public bool Foo()
{
try
{
//locking
//compare exchange returns the value that was in lockState before the compareExchange operation, so from that you can determine if you grabbed the lock or not
//if it was locked before, then you know the lock is not yours
if (Interlocked.CompareExchange(ref lockState, UNLOCKED, LOCKED) == LOCKED)
return false;
//lock is yours, do whatever stuff you like here, including throw exceptions
}
finally
{
//unlocking
//because this is in finally this lock will be released even if something goes wrong with your code
Interlocked.Exchange(ref lockstate, UNLOCKED);
}
}