WaitHandle.WaitAny and Semaphore class - c#

Edit: I'd like to plead temporary insanity for even asking this question, but it made sense at the time (see edit 2 below).
For a .NET 3.5 project, I have two types of resources (R1 and R2) that I need to check the availability of. Each resource type can have (say) 10 instances at any time.
When one of either types of resources becomes available, my worker thread needs to wake up (there is a variable number of threads). In an earlier implementation, there was only one resource type, for which I used a Semaphore to check availability.
Now I need to wait on two separate Semaphores (S1 and S2) that track availability of the resources.
WaitHandle[] waitHandles = new WaitHandle[] { s1, s2 };
int signalledHandle = WaitHandle.WaitAny(waitHandles);
switch (signalledHandle)
{
case 0:
// Do stuff
s1.Release();
case 1:
// Do stuff
s2.Release();
}
There is one problem with this however. From the MSDN documentation on WaitAny:
If more than one object becomes
signaled during the call, the return
value is the array index of the
signaled object with the smallest
index value of all the signaled
objects.
This suggests that it's possible that I decreased both my Semaphore counts by 1 after calling WaitAny. Because signalledHandle will indicate that s1 was signalled, I will start using resource R1, and release it when I'm done. However, since I do not know if S2 was signalled or not, the availability count on this resource might now be off. If this happens 10 times, my Semaphore will be permanently 'empty' and resource R2 will not be used at all anymore.
What is the best way to deal with this? Should I switch from using two semaphores to simple counters and an AutoResetEvent to signal when either counter is changed? Am I missing some more elegant approach?
Edit 1:
According to Ravadre, only one of the Semaphores will actually be altered after WaitAny. Slightly modifying his example seems to confirm this, but is there anyone that can point me to some piece of official documentation that specifies this?
Edit 2:
I was thinking about this on my way home. Only then I realized that this must be true for WaitAny to be of any use. This problem would not be restricted to Semaphores, but just about any type of synchronization object, making WaitAny practically useless.

If I understand your problem correctly, I think that your solution is perfectly ok, and you are just over interpreting the msdn quote. When calling WaitHandle.WaitAny() you will get the lowest index, but you will lock on only one waitHandle (semaphore in this case), check this sample code:
Semaphore s1 = new Semaphore(1, 2);
Semaphore s2 = new Semaphore(1, 2);
WaitHandle[] handles = new WaitHandle[] { s1, s2 };
int x = WaitHandle.WaitAny(handles);
int prevS1 = s1.Release();
int prevS2 = s2.Release();
In this scenario, prevS1 will be equal to 0, because semaphore s1 "was waited on", so it's counter has been reduced to 0, whereas prevS2 will be equal to 1, because it's state hasn't changed since it's instantiation (Release() method returns the counter before releasing, so returning 1 means "it was 1, now it's 2").
Another resource that you might want to look at : http://www.albahari.com/threading/part2.aspx#_Wait_Handles. Although it's not an "official " source, I think there's no reason to find it not reliable.

For your purpose, when calling WaitHandle.WaitAny() method the result doesn't matter. What matters is one WaitHandle was signaled, so you need to try to acquire lock/synchronization again.
void Main() {
var semaphoreOne = new SemaphoreSlim(0, 1);
var semaphoreTwo = new SemaphoreSlim(0, 1);
ReleaseSemaphoreAfterWhile(semaphoreOne);
bool firstAccepted;
bool secondAccepted = false;
while ((firstAccepted = semaphoreOne.Wait(0)) == false &&
(secondAccepted = semaphoreTwo.Wait(0)) == false) {
var waitHandles = new [] {
semaphoreOne.AvailableWaitHandle, semaphoreTwo.AvailableWaitHandle
};
WaitHandle.WaitAny(waitHandles);
Console.WriteLine("SemaphoreOne Before Lock = " + semaphoreOne.CurrentCount);
Console.WriteLine("SemaphoreTwo Before Lock = " + semaphoreTwo.CurrentCount);
}
if (firstAccepted) {
Console.WriteLine("semaphore 1 was locked");
} else if (secondAccepted) {
Console.WriteLine("semaphore 2 was locked");
} else {
throw new InvalidOperationException("no semaphores were signaled");
}
}
Random rd = new Random();
public void ReleaseSemaphoreAfterWhile(SemaphoreSlim semaphore) {
var sleepWork =(int)rd.Next(100, 1000);
ThreadPool.QueueUserWorkItem(t => {
Thread.Sleep(10000 + sleepWork);
semaphore.Release();
});
}
There are room for other implementations with the same idea/logic, but using while loop in that way you guaranteed that only one semaphore is going to get acquired, and if there's no room, it locks the thread until any of the WaitHandle gets signaled - considering SemaphoreSlim instance .Release() method.
Unfortunately (as pointed in the comments) they're some misunderstanding about thread synchronization in the web, but that code above should help you to solve your problem.

Related

Can this code cause a dead lock ?

using System;
using System.Threading;
namespace Threading
{
class Program
{
static void Main(string[] args)
{
Semaphore even = new Semaphore(1, 1);
Semaphore odd = new Semaphore(1, 1);
Thread evenThread = new Thread(() =>
{
for (int i = 1; i <= 100; i++)
{
even.WaitOne();
if(i % 2 == 0)
{
Console.WriteLine(i);
}
odd.Release();
}
});
Thread oddThread = new Thread(() =>
{
for(int i = 1; i <=100; i++)
{
odd.WaitOne();
if(i%2 != 0)
{
Console.WriteLine(i);
}
even.Release();
}
});
oddThread.Start();
evenThread.Start();
}
}
}
So I have written this code where one thread is producing Odd numbers and other is producing even numbers.
Using Semaphores I have made sure that they print numbers in orders and it works perfectly.
But I have a special situation in mind, for example each thread waits until the other thread releases its semaphore. So can there be a condition where both threads are waiting and no thread is making any progress and there is a deadlock situation ?
For deadlock to occur, two or more threads must be trying to acquire two or more resources, but do so in different orders. See e.g. Deadlock and Would you explain lock ordering?.
Your code does not involve more than one lock per thread† and so does not have the ability to deadlock.
It does have the ability to throw an exception. As noted in this comment, it is theoretically possible for one of the threads to get far enough ahead of the other thread that it attempts to release a semaphore lock that hasn't already been taken. For example, if evenThread is pre-empted (or simply doesn't get scheduled to start running) before it gets to its first call to even.WaitOne(), but oddThread gets to run, then oddThread can acquire the odd semaphore, handle the if statement, and then try to call even.Release() before evenThread has had a chance to acquire that semaphore.
This will result in a SemaphoreFullException being thrown by the call to Release().
This would be a more likely possibility on a single-CPU system, something that is very hard to find these days. :) But it's still theoretically possible for any CPU configuration.
† Actually, there's an implicit lock in the Console.WriteLine() call, which is thread-safe by design. But from your code's point of view, that's an atomic operation. It's not possible for your code to acquire that lock and then wait on another. So it doesn't have any relevance to your specific question.

c# thread infinite loop

I am trying to run two set of threads using AutoResetEvent to coordinate with each other;
After the first set (customer) is done, I used thread.join() to make sure all threads in the first set is done, the set the flag to stop the second thread. However, the thread.join() never complete and the debugger lost its track in between. The flag was never set so it keeps running.
Can someone please see what goes wrong here? Thanks!
private static AutoResetEvent tellerFree = new AutoResetEvent(true);
private volatile static bool doneflag = true;
public static void runMultTeller()
{
List<Thread> custThreads = new List<Thread>();
List<Thread> tellThreads = new List<Thread>();
for (int i = 1; i <= 50; i++)
{
Thread td = new Thread(getTeller);
td.Name = Convert.ToString(i);
custThreads.Add(td);
td.Start();
}
for (int j = 1; j <= 5; j++)
{
Thread tt = new Thread(doTelling);
tt.Name = Convert.ToString(j);
custThreads.Add(tt);
tt.Start();
}
foreach (Thread tc in custThreads)
{
if (tc.IsAlive)
{
tc.Join();
}
}
Console.WriteLine("Customer are done");
doneflag = false;
foreach (Thread t2 in tellThreads)
{
t2.Join();
}
Console.WriteLine("Teller are done");
Console.WriteLine("Done");
Thread.Sleep(5000);
}
static public void doTelling()
{
string name = Thread.CurrentThread.Name;
while (doneflag)
{
Console.WriteLine("teller#{0} serving", name);
Thread.Sleep(500);
Console.WriteLine("teller#{0} done", name);
tellerFree.Set();
}
}
static public void getTeller()
{
string name = Thread.CurrentThread.Name;
Console.WriteLine("customer#{0} Enter", name);
tellerFree.WaitOne();
Console.WriteLine("customer#{0} Leave", name);
}
You need to change:
custThreads.Add(tt);
in the second 'for' loop to:
tellThreads.Add(tt);
Otherwise your Join() call will wait forever for the doTelling() threads to finish which will never happen because the doneFlag will be never set.
Marking a boolean as volatile does not ensure that other threads observe that change immediately. It only ensures that if other threads observe the change, they will afterwards also observe all other writes that were done by the thread that wrote the volatile variable before writing it.
See http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/atomicity-volatility-and-immutability-are-different-part-three.aspx for more information:
Actually, that last bit is a lie. The true semantics of volatile reads and writes are considerably more complex than I've outlined here; in fact they do not actually guarantee that every processor stops what it is doing and updates caches to/from main memory. Rather, they provide weaker guarantees about how memory accesses before and after reads and writes may be observed to be ordered with respect to each other. Certain operations such as creating a new thread, entering a lock, or using one of the Interlocked family of methods introduce stronger guarantees about observation of ordering. If you want more details, read sections 3.10 and 10.5.3 of the C# 4.0 specification.
Frankly, I discourage you from ever making a volatile field. Volatile fields are a sign that you are doing something downright crazy: you're attempting to read and write the same value on two different threads without putting a lock in place. Locks guarantee that memory read or modified inside the lock is observed to be consistent, locks guarantee that only one thread accesses a given hunk of memory at a time, and so on.
UPDATE:
The code in the question has a bigger problem than just using volatile, as noticed by Oleg Mikhaylov. After correcting that problem, the program would probably work most of the time. Nevertheless, I leave this answer here, because the use of volatile is a second problem indeed.
I also heavily recommend that you read the book Threading in C# by Joseph Albahari.

Do a function just one time in only one thread in TPL

Here is the scenario:
I have a proxy that is shared among all the threads.
if this proxy gets blocked, then only ONE thread needs to dequeue a proxy from ProxyQueue, not all of them.
For dequeuing I am using interlocked right now so only one thread at a time can enter the function.
private static volatile string httpProxy = "1.1.1.1";
private static int usingResource = 0;
string localHttpProxy;
try
{
HttpWebRequest oReqReview = HttpWebRequest)WebRequest.Create(url);
if (IsHttpProxyDequeue)
{
oReqReview.Proxy = new WebProxy(httpProxy, 8998);
localHttpProxy = httpProxy;
}
HttpWebResponse respReview = (HttpWebResponse)oReqReview.GetResponse();
DoSomthing();
}
catch (Exception ex)
{
if (0 == Interlocked.Exchange(ref usingResource, 1))
{
if (ex.Message == "The remote server returned an error: (403) Forbidden." && httpProxy == localHttpProxy)
{
IsHttpProxyDequeue = currentQueueProxy.TryDequeue(out httpProxy);
}
Interlocked.Exchange(ref usingResource, 0);
}
}
Interlocked.Exchange does not block. It merely performs the swap of the value and reports the results. If the initial value of usingResource is 0 and three threads hit Interlocked.Exchange at exactly the same time, on one thread the Exchange() will return zero and set usingResource to 1, and on the other two threads Exchange() will return 1. Threads 2 and 3 will immediately continue executing with the first statement following the if block.
If you want threads 2 and 3 to block waiting for thread one to finish, then you should use something like a mutex lock, like the C# lock(object) syntax. Locks block threads.
Interlocked.Exchange does not block threads. Interlocked.Exchange is useful when writing non-blocking thread coordination. Interlocked.Exchange says "If I get the special value from this swap I'll take a detour and do this special operation, otherwise I'll just continue doing this other thing without waiting."
The Interlocked does provide synchronization on that value, so if multiple threads reach that point at the same time, only one of them will get a 0 back. All others will get a 1 back until the value gets set back to '0'.
You have a race condition in your code, which is probably what's causing the problem. Consider this sequence of events:
Thread A sees that `IsProxyDequeue` is `false`
Thread A calls `Interlocked.Exchange` and gets a value of '0'
Thread A logs the error
Thread B sees that `IsProxyDequeue` is `false`
Thread A dequeues the proxy and sets `usingResource` back to `0`
Thread B calls `Interlocked.Exchange` and gets a value of `0`
At this point, Thread B is also going to dequeue the proxy.
You'll need to come up with a different way of providing the synchronization. I suspect you'll want something like:
object lockObj = new object();
lock (lockObj)
{
if (!IsProxyDequeue)
{
// get the proxy
IsProxyDequeue = true;
}
oReqReview.Proxy = new WebProxy(httpProxy, 8989);
}
If you want to avoid the race condition, but you don't want other threads to block, then use Monitor.TryEnter rather than lock.

How to check the state of a semaphore

I want to check the state of a Semaphore to see if it is signalled or not (so if t is signalled, I can release it). How can I do this?
EDIT1:
I have two threads, one would wait on semaphore and the other should release a Semaphore. The problem is that the second thread may call Release() several times when the first thread is not waiting on it. So the second thread should detect that if it calls Release() it generate any error or not (it generate an error if you try to release a semaphore if nobody waiting on it). How can I do this? I know that I can use a flag to do this, but it is ugly. Is there any better way?
You can check to see if a Semaphore is signaled by calling WaitOne and passing a timeout value of 0 as a parameter. This will cause WaitOne to return immediately with a true or false value indicating whether the semaphore was signaled. This, of course, could change the state of the semaphore which makes it cumbersome to use.
Another reason why this trick will not help you is because a semaphore is said to be signaled when at least one count is available. It sounds like you want to know when the semaphore has all counts available. The Semaphore class does not have that exact ability. You can use the return value from Release to infer what the count is, but that causes the semaphore to change its state and, of course, it will still throw an exception if the semaphore already had all counts available prior to making the call.
What we need is a semaphore with a release operation that does not throw. This is not terribly difficult. The TryRelease method below will return true if a count became available or false if the semaphore was already at the maximumCount. Either way it will never throw an exception.
public class Semaphore
{
private int count = 0;
private int limit = 0;
private object locker = new object();
public Semaphore(int initialCount, int maximumCount)
{
count = initialCount;
limit = maximumCount;
}
public void Wait()
{
lock (locker)
{
while (count == 0)
{
Monitor.Wait(locker);
}
count--;
}
}
public bool TryRelease()
{
lock (locker)
{
if (count < limit)
{
count++;
Monitor.PulseAll(locker);
return true;
}
return false;
}
}
}
Looks like you need an other synchronization object because Semaphore does not provide such functionality to check whether it is signalled or not in specific moment of time.
Semaphore allows automatic triggering of code which awaiting for signalled state using WaitOne()/Release() methods for instance.
You can take a look at the new .NET 4 class SemaphoreSlim which exposes CurrentCount property perhaps you can leverage it.
CurrentCount
Gets the number of threads that will be allowed to enter
the SemaphoreSlim.
EDIT: Updated due to updated question
As a quick solution you can wrap semaphore.Release() by try/catch and handle SemaphoreFullException , does it work as you expected?
Using SemaphoreSlim you can check CurrentCount in such way:
int maxCount = 5;
SemaphoreSlim slim = new SemaphoreSlim(5, maxCount);
if (slim.CurrentCount == maxCount)
{
// generate error
}
else
{
slim.Release();
}
The way to implement semaphore using signalling is as follows. It doesn't make sense to be able to query the state outside of this, as it wouldn't be threadsafe.
Create an instance with maxThreads slots, initially all available:
var threadLimit = new Semaphore(maxThreads, maxThreads);
Use the following to wait (block) for a spare slot (in case maxThreads have already been taken):
threadLimit.WaitOne();
Use the following to release a slot:
threadLimit.Release(1);
There's a full example here.
Knowing when all counts are available in a semaphore is useful. I have used the following logic/solution. I am sharing here because I haven't seen any other solutions addressing this.
//List to add a variable number of handles
private List<WaitHandle> waitHandles;
//Using a mutex to make sure that only one thread/process enters this section
using (new Mutex(....))
{
waitHandles = new List<WaitHandle>();
int x = [Maximum number of slots available in the semaphore];
//In this for loop we spin a thread per each slot of the semaphore
//The idea is to consume all the slots in this process
//not allowing anything else to enter the code protected by the semaphore
for (int i = 0; i < x; i++)
{
Thread t = new Thread(new ParameterizedThreadStart(TWorker));
ManualResetEvent mre = new ManualResetEvent(false);
waitHandles.Add(mre);
t.Start(mre);
}
WaitHandle.WaitAll(waitHandles.ToArray());
[... do stuff here, all semaphore slots are blocked now ...]
//Release all slots
semaphore.Release(x);
}
private void TWorker(object sObject)
{
ManualResetEvent mre = (ManualResetEvent)sObject;
//This is an static Semaphore declared and instantiated somewhere else
semaphore.WaitOne();
mre.Set();
}

.NET Multithreading help

I have an application I have already started working with and it seems I need to rethink things a bit. The application is a winform application at the moment. Anyway, I allow the user to input the number of threads they would like to have running. I also allow the user to allocate the number of records to process per thread. What I have done is loop through the number of threads variable and create the threads accordingly. I am not performing any locking (and not sure I need to or not) on the threads. I am new to threading and am running into possible issue with multiple cores. I need some advice as to how I can make this perform better.
Before a thread is created some records are pulled from my database to be processed. That list object is sent to the thread and looped through. Once it reaches the end of the loop, the thread call the data functions to pull some new records, replacing the old ones in the list. This keeps going on until there are no more records. Here is my code:
private void CreateThreads()
{
_startTime = DateTime.Now;
var totalThreads = 0;
var totalRecords = 0;
progressThreadsCreated.Maximum = _threadCount;
progressThreadsCreated.Step = 1;
LabelThreadsCreated.Text = "0 / " + _threadCount.ToString();
this.Update();
for(var i = 1; i <= _threadCount; i++)
{
LabelThreadsCreated.Text = i + " / " + _threadCount;
progressThreadsCreated.Value = i;
var adapter = new Dystopia.DataAdapter();
var records = adapter.FindAllWithLocking(_recordsPerThread,_validationId,_validationDateTime);
if(records != null && records.Count > 0)
{
totalThreads += 1;
LabelTotalProcesses.Text = "Total Processes Created: " + totalThreads.ToString();
var paramss = new ArrayList { i, records };
var thread = new Thread(new ParameterizedThreadStart(ThreadWorker));
thread.Start(paramss);
}
this.Update();
}
}
private void ThreadWorker(object paramList)
{
try
{
var parms = (ArrayList) paramList;
var stopThread = false;
var threadCount = (int) parms[0];
var records = (List<Candidates>) parms[1];
var runOnce = false;
var adapter = new Dystopia.DataAdapter();
var lastCount = records.Count;
var runningCount = 0;
while (_stopThreads == false)
{
if (!runOnce)
{
CreateProgressArea(threadCount, records.Count);
}
else
{
ResetProgressBarMethod(threadCount, records.Count);
}
runOnce = true;
var counter = 0;
if (records.Count > 0)
{
foreach (var record in records)
{
counter += 1;
runningCount += 1;
_totalRecords += 1;
var rec = record;
var proc = new ProcRecords();
proc.Validate(ref rec);
adapter.Update(rec);
UpdateProgressBarMethod(threadCount, counter, emails.Count, runningCount);
if (_stopThreads)
{
break;
}
}
UpdateProgressBarMethod(threadCount, -1, lastCount, runningCount);
if (!_noRecordsInPool)
{
records = adapter.FindAllWithLocking(_recordsPerThread, _validationId, _validationDateTime);
if (records == null || records.Count <= 0)
{
_noRecordsInPool = true;
break;
}
else
{
lastCount = records.Count;
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Something simple you could do that would improve perf would be to use a ThreadPool to manage your thread creation. This allows the OS to allocate a group of thread paying the thread create penalty once instead of multiple times.
If you decide to move to .NET 4.0, Tasks would be another way to go.
I allow the user to input the number
of threads they would like to have
running. I also allow the user to
allocate the number of records to
process per thread.
This isn't something you really want to expose to the user. What are they supposed to put? How can they determine what's best? This is an implementation detail best left to you, or even better, the CLR or another library.
I am not performing any locking (and
not sure I need to or not) on the
threads.
The majority of issues you'll have with multithreading will come from shared state. Specifically, in your ThreadWorker method, it looks like you refer to the following shared data: _stopThreads, _totalRecords, _noRecordsInPool, _recordsPerThread, _validationId, and _validationDateTime.
Just because these data are shared, however, doesn't mean you'll have issues. It all depends on who reads and writes them. For example, I think _recordsPerThread is only written once initially, and then read by all threads, which is fine. _totalRecords, however, is both read and written by each thread. You can run into threading issues here since _totalRecords += 1; consists of a non-atomic read-then-write. In other words, you could have two threads read the value of _totalRecords (say they both read the value 5), then increment their copy and then write it back. They'll both write back the value 6, which is now incorrect since it should be 7. This is a classic race condition. For this particular case, you could use Interlocked.Increment to atomically update the field.
In general, to do synchronization between threads in C#, you can use the classes in the System.Threading namespace, e.g. Mutex, Semaphore, and probably the most common, Monitor (equivalent to lock) which allows only one thread to execute a specific portion of code at a time. The mechanism you use to synchronize depends entirely on your performance requirements. For example, if you throw a lock around the body of your ThreadWorker, you'll destroy any performance gains you got through multithreading by effectively serializing the work. Safe, but slow :( On the other hand, if you use Interlocked.Increment and judiciously add other synchronization where necessary, you'll maintain your performance and your app will be correct :)
Once you've gotten your worker method to be thread-safe, you should use some other mechanism to manage your threads. ThreadPool was mentioned, and you could also use the Task Parallel Library, which abstracts over the ThreadPool and smartly determines and scales how many threads to use. This way, you take the burden off of the user to determine what magic number of threads they should run.
The obvious answer is to question why you want threads in the first place? Where is the analysis and benchmarks that show that using threads will be an advantage?
How are you ensuring that non-gui threads do not interact with the gui? How are you ensuring that no two threads interact with the same variables or datastructures in an unsafe way? Even if you realise you do need to use locking, how are you ensuring that the locks don't result in each thread processing their workload serially, removing any advantages that multiple threads might have provided?

Categories

Resources