The true power of semaphore is :
Limits the number of threads that can access a resource or pool of
resources concurrently
That is understood and clear.
But I never got a chance to play with the overload of Wait which accepts a timeout integer, however - this seems to allow multiple threads get into the critical section although I've explicitly set semaphore not to allow more than one thread at a time:
private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1);
private void Main()
{
Task.Run(() => DelayAndIncrementAsync());
Task.Run(() => DelayAndIncrementAsync());
}
private void DelayAndIncrementAsync()
{
_mutex.Wait(2000);
try
{
Console.WriteLine(0);
Thread.Sleep(TimeSpan.FromSeconds(5));
Console.WriteLine(1);
}
finally
{
_mutex.Release();
}
}
The first thread is entering the mutex zone, prints "0", waits 5 seconds, meanwhile after 2 seconds the other thread ALSO enters the critical section?
Question
Isn't it defeating the whole purpose of semaphore?
What are the real life scenarios which I would use this timeout, especially when the basic rule is -
"Semaphore = Limits the number of threads that can access a resource
or pool of resources concurrently
You need to check the return value of the wait. The Timeout based wait will try for 2 seconds to take the mutex then return. You need to check if the return value is true (i.e you have the mutex) or not.
Edit: Also keep in mind that the timeout based wait will return immediately if the semaphore is available, so you cant use this to prevent an infinite loop in the code via this technique.
private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1);
void Main()
{
Task.Run(()=>DelayAndIncrementAsync());
Task.Run(()=>DelayAndIncrementAsync());
}
public void DelayAndIncrementAsync()
{
if (_mutex.Wait(2000))
{
try
{
Console.WriteLine(0);
Thread.Sleep(TimeSpan.FromSeconds(5));
Console.WriteLine(1);
}
finally
{
_mutex.Release();
}
} else {
//oh noes I don't have the mutex
}
}
Your misconception is that there is an implicit "mutex zone" which is not defined by you.
The overload of Wait which you are using returns a boolean value which tells you whether or not the mutex was successfully entered.
What you are doing in your example is entering the critical zone whether or not the thread has acquired the mutex, making it redundant.
Generally, you would want to use this overload in any situation where you want to try to enter a mutex but also have a fallback strategy in case that it is not currently possible to acquire the mutex within the allotted time.
This will make people cringe but using the timeout (and confirming it did timeout) is a good way to log and track deadlock bugs. Sure if you wrote your program correctly you wouldn't need these, but I've personally used this for this purpose which has saved me a lot of time.
So yes it does defeat the purpose (in most cases) if you let it timeout and then hit the critical section with multiple threads. But it can be useful to log or detect a deadlock bug.
There are also use cases where you want multiple threads to access the critical section, but only in specific scenarios. Eg it would not be fatal and simply be undesirable for it occur. Eg you aren't using the semaphore to stop a cross thread crash, but rather something else.
Related
I work on data that is mostly read and I want to perform these works as efficiently as possible, and I need to provide thread-safe access to it.
Any explanations on my problem would be welcome. Thanks
So the basics of creating a thread
//
Threat t = new Thread (My_Function);
// or
Thread t = new Thread (()=>
{
//your code here
});
t.start();
If you want to make the read thread safe you can use the "lock statement inside the thread on the resources that you want to ensure serial access
lock (Read_resource_object)
{
}
What lock does is, is the first time code runs over the lock statement it will "lock" the resource until the then of the curly braces. This does not prevent other code from accessing that object, rather, if any other code calls a lock on that resource, that code blocks until the current thread that locked it, unlocks it. Of course be very careful to make sure your don't get a thread lock,which usually occurs if inside your first lock somehow the flow of the code results in trying to lock the same code before it gets unlocked. Other than that I would recomend reading some tutorials on this because mutli threading and thread saftey are difficult and complicated!
Also lookup tasks as well they wrap threads and provide additional functionality.
I found this answer in C# 6 Cookbook
Use ReaderWriterLockSlim to give multiple-read/single-write access with the capacity to upgrade the lock from read to write. As an example, say a developer is starting a new project. Unfortunately, the project is understaffed, so the developer has to respond to tasks from many other individuals on the team. Each of the other team members will also ask the developer for status updates on their tasks, and some can even change the priority of the tasks the developer is assigned. The developer is assigned a task via the AddTask method. To protect the Developer Tasks collection we use a write lock on ReaderWriterLockSlim, calling EnterWrite Lock when adding the task to the DeveloperTasks collection and ExitWriteLock when the addition is complete:
public void AddTask(DeveloperTask newTask)
{
try
{
Lock.EnterWriteLock();
// if we already have this task (unique by name)
// then just accept the add as sometimes people
// give you the same task more than once :)
var taskQuery = from t in DeveloperTasks
where t == newTask
select t;
if (taskQuery.Count<DeveloperTask>() == 0)
{
Console.WriteLine($"Task {newTask.Name} was added to developer");
DeveloperTasks.Add(newTask);
}
}
finally
{
Lock.ExitWriteLock();
}
}
When a project team member needs to know about the status of a task, they call the IsTaskDone method, which uses a read lock on the ReaderWriterLockSlim by calling EnterReadLock and ExitReadLock:
public bool IsTaskDone(string taskName)
{
try
{
Lock.EnterReadLock();
var taskQuery = from t in DeveloperTasks
where t.Name == taskName
select t;
if (taskQuery.Count<DeveloperTask>() > 0)
{
DeveloperTask task = taskQuery.First<DeveloperTask>();
Console.WriteLine($"Task {task.Name} status was reported.");
return task.Status;
}
}
finally
{
Lock.ExitReadLock();
}
return false;
}
There are certain managerial members of the team who have the right to increase the priority of the tasks they assigned to the developer. They accomplish this by calling the IncreasePriority method on the Developer. IncreasePriority uses an upgradable lock on ReaderWriterLockSlim by first calling the EnterUpgradeable Lock method to acquire a read lock, and then, if the task is in the queue, upgrading to a write lock in order to adjust the priority of the task. Once the priority is adjusted,
the write lock is released, which degrades the lock back to a read lock, and that lock is released through a call to ExitUpgradeableReadLock:
public void IncreasePriority(string taskName)
{
try
{
Lock.EnterUpgradeableReadLock();
var taskQuery = from t in DeveloperTasks
where t.Name == taskName
select t;
if (taskQuery.Count<DeveloperTask>() > 0)
{
DeveloperTask task = taskQuery.First<DeveloperTask>();
Lock.EnterWriteLock(); task.Priority++;
Console.WriteLine($"Task {task.Name}" + $" priority was increased to {task.Priority}" + " for developer"); Lock.ExitWriteLock();
}
}
finally
{
Lock.ExitUpgradeableReadLock();
}
}
Discussion The ReaderWriterLockSlim was created to replace the existing ReaderWriterLock for a number of reasons:
ReaderWriterLock was more than five times slower than using a
Monitor.
Recursion semantics of ReaderWriterLock were not standard and were
broken in some thread reentrancy cases.
The upgrade lock method is nonatomic in ReaderWriterLock. While the
ReaderWriterLockSlim is only about two times slower than the Monitor,
it is more flexible and prioritizes writes, so in “few write, many read” scenarios, it is more scalable than the Monitor.
There are also methods to determine what type of lock is held as well
as how many threads are waiting to acquire it. By default, lock
acquisition recursion is disallowed. If you call EnterReadLock twice,
you get a LockRecursionException. You can enable lock recursion by passing a Lock RecusionPolicy.SupportsRecursion enumeration value to the constructor overload of ReaderWriterLockSlim that accepts it.
Even though it is possible to enable lock recursion, it is generally
discouraged, as it complicates matters and creates issues that are
not fun to debug.
One of the things I'm having a hard time to understand in multi-threaded programming is that fact that when one thread reaches a line that calls WaitOne(), how do I know which other threads are involved? Where or how can I find (or understand) how the WaitHandle receives the signal? For example, I'm looking at this code right now:
private void RunSync(object state, ElapsedEventArgs elapsedEventArgs)
{
_mutex.WaitOne();
using (var sync = GWSSync.BuildSynchronizer(_log))
{
try
{
sync.Syncronize();
}
catch(Exception ex)
{
_log.Write(string.Format("Error during synchronization : {0}", ex));
}
}
_mutex.ReleaseMutex();
_syncTimer.Interval = TimeBeforeNextSync().TotalMilliseconds;
_syncTimer.Start();
}
There are a few methods like this in the file (i.e RunThis(), RunThat()). These methods run inside a Windows service and are called when a Timer elapses. Each of these methods are called using different Timers and set up like this:
//Synchro
var timeBeforeFirstSync = TimeBeforeNextSync();
_syncTimer = new System.Timers.Timer(timeBeforeFirstSync.TotalMilliseconds);
_syncTimer.AutoReset = false;
_syncTimer.Elapsed += RunSync;
_syncTimer.Start();
I understand that when the Timer elapses, the RunSync method will run. But when it hits the WaitOne() line, the thread is blocked. But who is it waiting for? Which "other" thread will send the signal?
WaitHandle is an abstraction, as stated in the documentation:
Encapsulates operating system–specific objects that wait for exclusive access to shared resources.
You don't know which other threads are involved, but you do know which other code is involved by checking the usage of the handle (_mutex in your case). Every WaitHandle derived class inherits WaitOne, but what happens after successful wait and how it's get signalled is specific. For instance, in your example _mutex most probably is a Mutex class, so WaitOne acts like "wait until it's free and take ownership" while the ReleaseMutex acts like "release ownership and signal". With that in mind, it should be obvious what all these methods do - ensuring that while RunThis you cannot RunThat and vise versa.
I sometimes encounter code in the following form:
while (true) {
//do something
Thread.Sleep(1000);
}
I was wondering if this is considered good or bad practice and if there are any alternatives.
Usually I "find" such code in the main-function of services.
I recently saw code in the "Run" function in a windows azure worker role which had the following form:
ClassXYZ xyz = new ClassXYZ(); //ClassXYZ creates separate Threads which execute code
while (true) {
Thread.Sleep(1000);
}
I assume there are better ways to prevent a service (or azure worker role) from exiting.
Does anyone have a suggestion for me?
Well when you do that with Thread.Sleep(1000), your processor wastes a tiny amount of time to wake up and do nothing.
You could do something similar with CancelationTokenSource.
When you call WaitOne(), it will wait until it receives a signal.
CancellationTokenSource cancelSource = new CancellationTokenSource();
public override void Run()
{
//do stuff
cancelSource.Token.WaitHandle.WaitOne();
}
public override void OnStop()
{
cancelSource.Cancel();
}
This will keep the Run() method from exiting without wasting your CPU time on busy waiting.
An alternative approach may be using an AutoResetEvent and instantiate it signaled by default.
public class Program
{
public static readonly AutoResetEvent ResetEvent = new AutoResetEvent(true);
public static void Main(string[] args)
{
Task.Factory.StartNew
(
() =>
{
// Imagine sleep is a long task which ends in 10 seconds
Thread.Sleep(10000);
// We release the whole AutoResetEvent
ResetEvent.Set();
}
);
// Once other thread sets the AutoResetEvent, the program ends
ResetEvent.WaitOne();
}
}
Is the so-called while(true) a bad practice?
Well, in fact, a literal true as while loop condition may be considered a bad practice, since it's an unbrekeable loop: I would always use a variable condition which may result in true or false.
When I would use a while loop or something like the AutoResetEvent approach?
When to use while loop...
...when you need to execute code while waiting the program to end.
When to use AutoResetEvent approach...
...when you just need to hold the main thread in order to prevent the program to end, but such main thread just needs to wait until some other thread requests a program exit.
If you see code like this...
while (true)
{
//do something
Thread.Sleep(1000);
}
It's most likely using Sleep() as a means of waiting for some event to occur — something like user input/interaction, a change in the file system (such as a file being created or modified in a folder, network or device event, etc. That would suggest using more appropriate tools:
If the code is waiting for a change in the file system, use a FileSystemWatcher.
If the code is waiting for a thread or process to complete, or a network event to occur, use the appropriate synchronization primitive and WaitOne(), WaitAny() or WaitAll() as appropriate. If you use an overload with a timeout in a loop, it gives you cancelability as well.
But without knowing the actual context, it's rather hard to say categorically that it's either good, bad or indifferent. If you've got a daemon running that has to poll on a regular basis (say an NTP client), a loop like that would make perfect sense (though the daemon would need some logic to monitor for shutdown events occuring.) And even with something like that, you could replace it with a scheduled task: a different, but not necessarily better, design.
If you use while(true) you have no programmatic means of ending the loop from outside the loop.
I'd prefer, at least, a while(mySingletonValue) which would allow us to switch the loop as needed.
An additional approach would be to remove the functional behavior from the looping behavior. Your loop my still be infinite but it calls a function defined elsewhere. Therefore the looping behavior is completely isolated to what is being executed by the loop:
while(GetMySingletonValue())
{
someFunction();
}
In this way your singleton controls the looping behavior entirely.
There are better ways to keep the Azure Service and exit when needed.
Refer:
http://magnusmartensson.com/howto-wait-in-a-workerrole-using-system-timers-timer-and-system-threading-eventwaithandle-over-system-threading-thread-sleep
http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/azure-worker-role-exiting-safely/
It really depends on that //do something on how it determines when to break out of the loop.
In general terms, more appropriate way to do it is to use some synchronization primitive (like ManualResetEvent) to wait on, and the code that processes and triggers the break of the loop (on the other thread) to signal on that primitive. This way you don't have thread wasting resources by being scheduled in every second to do nothing, and is a much cleaner way to do it.
I personally don't like Thread.Sleep code. Because it locks the main thread. You can write something like this, if it is a windows application besides it allows you more flexibility and you can call it async:
bool switchControl = true;
while (switchControl) {
//do something
await Wait(1);
}
async void Wait(int Seconds)
{
DateTime Tthen = DateTime.Now;
do
{
Application.DoEvents(); //Or something else or leave empty;
} while (Tthen.AddSeconds(Seconds) > DateTime.Now);
}
I want to call a task at a specified interval. And avoid calling a new task unless the last has already completed.
private async void OnTimerTick(object sender, object e)
{
if (_criticalSection.IsEntered()) return; // only allow 1 at any given time, ignore the rest
using (var section = await _criticalSection.EnterAsync())
{
await update();
}
}
How do I achieve this? Any suggestions for a better pattern?
A critical section (like a Window's mutex) is for mutual exclusion: only allowing a single thread into a code path.
But that's not what you are trying to do: you need something that will tell you if something is happening.
A better approach would be a Manual Reset Event: set it (also know as signalled) at the start of the task and reset at the end. Then you can check if it is signalled by waiting on it with a timeout of zero for a normal Window's event, or with the applicable member for other types of event.
As this appears to be all in a single process a good starting point is System.Threading.ManualRestEventSlim. Used something like:
// One off initialisation somewhere at class scope
private static ManualResetEventSlim taskRunning = new ManualResetEventSlim();
private static object taskLock = new Object();
// code called from the timer, do in a lock to avoid race conditions with two
// or more threads call this.
lock (taskLock) {
if (!taskRunning.IsSet) {
StartTheTask(); // assuming this does not return until task is running.
}
}
// At the outermost scope of the code in the task:
try {
Debug.Assert(!taskRunning.IsSet); // Paranoia is good when doing threading
taskRunning.Set();
// Task impementation
} finally {
Debug.Assert(taskRunning.IsSet); // Paranoia is good when doing threading
taskRunning.Reset();
}
Another approach would be to always start the task, but have it check the event, if set then immediately exit. This would still need the lock to avoid races between the IsSet and Set() calls across threads. This second approach keeps the checking code together at the cost of briefly having another task running (unless that is common I would likely take this approach for the code locality).
What does it mean when one says no polling is allowed when implimenting your thread solution since it's wasteful, it has latency and it's non-deterministic. Threads should not use polling to signal each other.
EDIT
Based on your answers so far, I believe my threading implementation (taken from: http://www.albahari.com/threading/part2.aspx#_AutoResetEvent) below is not using polling. Please correct me if I am wrong.
using System;
using System.Threading;
using System.Collections.Generic;
class ProducerConsumerQueue : IDisposable {
EventWaitHandle _wh = new AutoResetEvent (false);
Thread _worker;
readonly object _locker = new object();
Queue<string> _tasks = new Queue<string>();
public ProducerConsumerQueue() (
_worker = new Thread (Work);
_worker.Start();
}
public void EnqueueTask (string task) (
lock (_locker) _tasks.Enqueue (task);
_wh.Set();
}
public void Dispose() (
EnqueueTask (null); // Signal the consumer to exit.
_worker.Join(); // Wait for the consumer's thread to finish.
_wh.Close(); // Release any OS resources.
}
void Work() (
while (true)
{
string task = null;
lock (_locker)
if (_tasks.Count > 0)
{
task = _tasks.Dequeue();
if (task == null) return;
}
if (task != null)
{
Console.WriteLine ("Performing task: " + task);
Thread.Sleep (1000); // simulate work...
}
else
_wh.WaitOne(); // No more tasks - wait for a signal
}
}
}
Your question is very unclear, but typically "polling" refers to periodically checking for a condition, or sampling a value. For example:
while (true)
{
Task task = GetNextTask();
if (task != null)
{
task.Execute();
}
else
{
Thread.Sleep(5000); // Avoid tight-looping
}
}
Just sleeping is a relatively inefficient way of doing this - it's better if there's some coordination so that the thread can wake up immediately when something interesting happens, e.g. via Monitor.Wait/Pulse or Manual/AutoResetEvent... but depending on the context, that's not always possible.
In some contexts you may not want the thread to actually sleep - you may want it to become available for other work. For example, you might use a Timer of one sort or other to periodically poll a mailbox to see whether there's any incoming mail - but you don't need the thread to actually be sleeping when it's not checking; it can be reused by another thread-pool task.
Here you go: check out this website:
http://msdn.microsoft.com/en-us/library/dsw9f9ts%28VS.71%29.aspx
Synchronization Techniques
There are two approaches to synchronization, polling and using synchronization objects. Polling repeatedly checks the status of an asynchronous call from within a loop. Polling is the least efficient way to manage threads because it wastes resources by repeatedly checking the status of the various thread properties.
For example, the IsAlive property can be used when polling to see if a thread has exited. Use this property with caution because a thread that is alive is not necessarily running. You can use the thread's ThreadState property to get more detailed information about a thread's status. Because threads can be in more than one state at any given time, the value stored in ThreadState can be a combination of the values in the System.Threading.Threadstate enumeration. Consequently, you should carefully check all relevant thread states when polling. For example, if a thread's state indicates that it is not Running, it may be done. On the other hand, it may be suspended or sleeping.
Waiting for a Thread to Finish
The Thread.Join method is useful for determining if a thread has completed before starting another task. The Join method waits a specified amount of time for a thread to end. If the thread ends before the timeout, Join returns True; otherwise it returns False. For information on Join, see Thread.Join Method
Polling sacrifices many of the advantages of multithreading in return for control over the order that threads run. Because it is so inefficient, polling generally not recommended. A more efficient approach would use the Join method to control threads. Join causes a calling procedure to wait either until a thread is done or until the call times out if a timeout is specified. The name, join, is based on the idea that creating a new thread is a fork in the execution path. You use Join to merge separate execution paths into a single thread again
One point should be clear: Join is a synchronous or blocking call. Once you call Join or a wait method of a wait handle, the calling procedure stops and waits for the thread to signal that it is done.
Copy
Sub JoinThreads()
Dim Thread1 As New System.Threading.Thread(AddressOf SomeTask)
Thread1.Start()
Thread1.Join() ' Wait for the thread to finish.
MsgBox("Thread is done")
End Sub
These simple ways of controlling threads, which are useful when you are managing a small number of threads, are difficult to use with large projects. The next section discusses some advanced techniques you can use to synchronize threads.
Hope this helps.
PK
Polling can be used in reference to the four asyncronous patterns .NET uses for delegate execution.
The 4 types (I've taken these descriptions from this well explained answer) are:
Polling: waiting in a loop for IAsyncResult.Completed to be true
I'll call you
You call me
I don't care what happens (fire and forget)
So for an example of 1:
Action<IAsyncResult> myAction = (IAsyncResult ar) =>
{
// Send Nigerian Prince emails
Console.WriteLine("Starting task");
Thread.Sleep(2000);
// Finished
Console.WriteLine("Finished task");
};
IAsyncResult result = myAction.BeginInvoke(null,null,null);
while (!result.IsCompleted)
{
// Do something while you wait
Console.WriteLine("I'm waiting...");
}
There's alternative ways of polling, but in general it means "I we there yet", "I we there yet", "I we there yet"
What does it mean when one says no
polling is allowed when implimenting
your thread solution since it's
wasteful, it has latency and it's
non-deterministic. Threads should not
use polling to signal each other.
I would have to see the context in which this statement was made to express an opinion on it either way. However, taken as-is it is patently false. Polling is a very common and very accepted strategy for signaling threads.
Pretty much all lock-free thread signaling strategies use polling in some form or another. This is clearly evident in how these strategies typically spin around in a loop until a certain condition is met.
The most frequently used scenario is the case of signaling a worker thread that it is time to terminate. The worker thread will periodically poll a bool flag at safe points to see if a shutdown was requested.
private volatile bool shutdownRequested;
void WorkerThread()
{
while (true)
{
// Do some work here.
// This is a safe point so see if a shutdown was requested.
if (shutdownRequested) break;
// Do some more work here.
}
}