making synchronized array that implements read\write methods - c#

I have a class that has the fields: array of messages and current number of messages and the methods read\write.
When someone write, it puts the message into the array and increment current number of messages by one, and when someone trying to read it first decrease
current number of messages and then returns the last message.
I want to make this class to be Synchronized so it will allow to threads to write and read(when the array is empty i want that the thread will wait until will be something to read) from him and prevent data races.
I did this class that implements :
class SynchronizedDATAStructure : DATAStructure
{
private Mutex mutexR = new Mutex();
private Mutex mutexW = new Mutex();
private Semaphore semaphore = new Semaphore(0, int.MaxValue);
private Semaphore semaphore2 = new Semaphore(1, 1);
public override void Write(Message msg)
{
mutexW.WaitOne(); // allows only one thread each time to write
semaphore2.WaitOne(); // checks if nobody is reading
base.Write(msg); // writing
semaphore.Release(); // counts number of messages
semaphore2.Release(); // finish to write
mutexW.ReleaseMutex(); // finish the function
}
public override Message Read()
{
mutexR.WaitOne(); // allows only one thread each time to read
semaphore.WaitOne(); // checks if there are messages
semaphore2.WaitOne(); // checks if nobody is writing
Message msg1 = base.Read(); // reading
semaphore2.Release(); // finish to read
mutexR.ReleaseMutex(); // finish the function
return msg1; // returns the messge
}
When the threads start to write\read i got outOfBounds after while when thread trying to read from empty array.

You can make your code much simpler using Monitor:
class SynchronizedDATAStructure : DATAStructure
{
private readonly object syncRoot = new object();
public int MessageCount { get; private set; }
public override void Write(Message msg)
{
lock (syncRoot)
{
base.Write(msg);
MessageCount++;
Monitor.Pulse(syncRoot);
}
}
public override Message Read()
{
lock (syncRoot)
{
while (MessageCount <= 0)
{
Monitor.Wait(syncRoot);
}
MessageCount--;
return base.Read();
}
}
}

Related

Fence in classes - single writer multiple readers

have another confusion about locking in C#.
The problem is sharing a state among diffrent threads.
Following scenario:
A thread processes a state machine. This machine, for example, counts up a value with delay. The machine thread reads this value and increments. Other threads shall now be able to read this count value. Actually I have more values than just a a single count, so I prepared a class which holds the shared values. This looks like this:
IStatus is a suitable private interface. Summaries are removed since not in English.
public class Status : ICloneable, IStatus
{
private object locker;
public bool Run { get; private set; }
public uint SecondRemain { get; private set; }
// ... and some more value types
public Status()
{
locker = new object();
}
void IStatus.SetRun(bool enable)
{
lock (locker)
{
Run = enable;
}
}
void IStatus.SetSecondRemain (uint value)
{
lock (locker)
{
SecondRemain = value;
}
}
// ... and some more set of value types
public object Clone()
{
object copy;
lock (locker)
{
copy = MemberwiseClone();
// Since it is a "new" object, we decouple the lock
((Status)copy).locker = new object();
}
return copy;
}
In main class where the state machine and its thread lives in:
private Status shared;
// Shall be accessible by any thread at any time
public Status GetStatus()
{
// Clones thread-safe, fenced by locker
return (Status) shared.Clone();
}
// Will be accessed only by inner thread
private void AnyMethodCalledStateMachineThread()
{
// Get the current remaining second value.
// No fence here ??
uint value = shared.SecondRemain;
// fences by locker
((IStatus) shared).SetSecondRemain (value++);
}
What we see now is, only the inner thread will read and write to some values. This thread will read what it has previously written. To ensure other threads can read this, it is locked.
External threads can only get a full copy by lock statement.
But does internal thread itself needs lock, too, when reading single properties or do I have to put lock around these properties (with extra field)?
EDIT
This is the requested sort of code which runs the thread
var thread;
private void Start()
{
thread = new Thread(new ThreadStart(ProducerMain));
thread.Start();
}
// Example, no real code
private void ProducerMain()
{
while ( ...)
{
Thread.Sleep(1000);
AnyMethodCalledStateMachineThread();
}
}

Release a lock before waiting, and re-acquire it after

In Java, you can associate multiple Condition objects to a single ReentrantLock. What would the C# equivalent be?
Real-world example: The example implementation in the Java Condition documentation uses two Condition objects, notFull and notEmpty, tied to the same lock. How could that example be translated to C#?
Background: I often find Java code using two Condition objects to signal various states, associated to the same Lock; in C#, it seems that you can either
call Monitor.Enter on an object, and then Monitor.WaitOne/Monitor.Pulse, but that's just one condition.
use multiple Auto/ManualResetEvent objects, but these cannot atomically reacquire a given lock after waiting.
Note: I can think of one way: using Monitor.WaitOne/Monitor.PulseAll on a single object, and checking for the condition after waking up; that's what you do in Java as well to protect against spurious wake-ups. It doesn't really do, though, because it forces you to call PulseAll instead of Pulse, since Pulse might wake up a thread waiting on another condition. Unfortunately, using PulseAll instead of Pulse has performance implications (threads competing for the same lock).
I think if you are doing new development and can do .NET 4 or above, you'll be better served by the new concurrent collection classes, like ConcurrentQueue.
But if you can't make that move, and to strictly answer your question, in .NET this is somewhat simplified imho, to implement a prod/cons pattern you would just do wait and then pulse like below (note that I typed this on notepad)
// max is 1000 items in queue
private int _count = 1000;
private Queue<string> _myQueue = new Queue<string>();
private static object _door = new object();
public void AddItem(string someItem)
{
lock (_door)
{
while (_myQueue.Count == _count)
{
// reached max item, let's wait 'till there is room
Monitor.Wait(_door);
}
_myQueue.Enqueue(someItem);
// signal so if there are therads waiting for items to be inserted are waken up
// one at a time, so they don't try to dequeue items that are not there
Monitor.Pulse(_door);
}
}
public string RemoveItem()
{
string item = null;
lock (_door)
{
while (_myQueue.Count == 0)
{
// no items in queue, wait 'till there are items
Monitor.Wait(_door);
}
item = _myQueue.Dequeue();
// signal we've taken something out
// so if there are threads waiting, will be waken up one at a time so we don't overfill our queue
Monitor.Pulse(_door);
}
return item;
}
Update: To clear up any confusion, note that Monitor.Wait releases a lock, therefore you won't get a deadlock
#Jason If the queue is full and you wake only ONE thread, you are not guaranteed that thread is a consumer. It might be a producer and you get stuck.
I haven't come across much C# code that would want to share state within a lock. Without rolling your own you could use a SemaphoreSlim (but I recommend ConcurrentQueue(T) or BlockingCollection(T)).
public class BoundedBuffer<T>
{
private readonly SemaphoreSlim _locker = new SemaphoreSlim(1,1);
private readonly int _maxCount = 1000;
private readonly Queue<T> _items;
public int Count { get { return _items.Count; } }
public BoundedBuffer()
{
_items = new Queue<T>(_maxCount);
}
public BoundedBuffer(int maxCount)
{
_maxCount = maxCount;
_items = new Queue<T>(_maxCount);
}
public void Put(T item, CancellationToken token)
{
_locker.Wait(token);
try
{
while(_maxCount == _items.Count)
{
_locker.Release();
Thread.SpinWait(1000);
_locker.Wait(token);
}
_items.Enqueue(item);
}
catch(OperationCanceledException)
{
try
{
_locker.Release();
}
catch(SemaphoreFullException) { }
throw;
}
finally
{
if(!token.IsCancellationRequested)
{
_locker.Release();
}
}
}
public T Take(CancellationToken token)
{
_locker.Wait(token);
try
{
while(0 == _items.Count)
{
_locker.Release();
Thread.SpinWait(1000);
_locker.Wait(token);
}
return _items.Dequeue();
}
catch(OperationCanceledException)
{
try
{
_locker.Release();
}
catch(SemaphoreFullException) { }
throw;
}
finally
{
if(!token.IsCancellationRequested)
{
_locker.Release();
}
}
}
}

Notify thread when data is added in queue

I have one thread which is adding data in the queue, now I want that other thread should get notified when the data is added so that it can start processing data from queue.
one option is thread will poll the queue continuously to see if count is more than zero but I think this is not good way, any other suggestion will be greatly appreciated
Any suggestion how I can achieve this, I am using .net framework 3.5.
and what if i have two thread one is doing q.Enqueue(data) and other is doing q.dequeue(), in this case do i need to manage the lock..?
You can use ManualResetEvent to notify a thread.
ManualResetEvent e = new ManualResetEvent(false);
After each q.enqueue(); do e.Set() and in the processing thread, you wait for items with e.WaitOne().
If you do processing inside a loop, you should do e.Reset() right after e.WaitOne().
I don't use queue's, because I'd rather batch process them. This is more usefull when you have to open/close (log)files, open/close databases. Here is an example how I create such:
// J. van Langen
public abstract class QueueHandler<T> : IDisposable
{
// some events to trigger.
ManualResetEvent _terminating = new ManualResetEvent(false);
ManualResetEvent _terminated = new ManualResetEvent(false);
AutoResetEvent _needProcessing = new AutoResetEvent(false);
// my 'queue'
private List<T> _queue = new List<T>();
public QueueHandler()
{
new Thread(new ThreadStart(() =>
{
// what handles it should wait on.
WaitHandle[] handles = new WaitHandle[] { _terminating, _needProcessing };
// while not terminating, loop (0 timeout)
while (!_terminating.WaitOne(0))
{
// wait on the _terminating and the _needprocessing handle.
WaitHandle.WaitAny(handles);
// my temporay array to store the current items.
T[] itemsCopy;
// lock the queue
lock (_queue)
{
// create a 'copy'
itemsCopy = _queue.ToArray();
// clear the queue.
_queue.Clear();
}
if (itemsCopy.Length > 0)
HandleItems(itemsCopy);
}
// the thread is done.
_terminated.Set();
})).Start();
}
public abstract void HandleItems(T[] items);
public void Enqueue(T item)
{
// lock the queue to add the item.
lock (_queue)
_queue.Add(item);
_needProcessing.Set();
}
// batch
public void Enqueue(IEnumerable<T> items)
{
// lock the queue to add multiple items.
lock (_queue)
_queue.AddRange(items);
_needProcessing.Set();
}
public void Dispose()
{
// let the thread know it should stop.
_terminating.Set();
// wait until the thread is stopped.
_terminated.WaitOne();
}
}
For the _terminating/_terminated I use a ManualResetEvent because those are only set ones.
For the _needProcessing I use an AutoResetEvent It can't be done with a ManualResetEvent, because when it's triggered, another thread could Set it again, so if you Reset it after the WaitHandle.WaitAny you could undone newly added items. (hmmm, if anyone could explain this easier, be welcome. :)
Example:
public class QueueItem
{
}
public class MyQueue : QueueHandler<QueueItem>
{
public override void HandleItems(QueueItem[] items)
{
// do your thing.
}
}
public void Test()
{
MyQueue queue = new MyQueue();
QueueItem item = new QueueItem();
queue.Enqueue(item);
QueueItem[] batch = new QueueItem[]
{
new QueueItem(),
new QueueItem()
};
queue.Enqueue(batch);
// even on dispose, all queued items will be processed in order to stop the QueueHandler.
queue.Dispose();
}
Use the BlockingCollection class. This nice thing about it is that the Take method blocks (without polling) if the queue is empty. It is included in .NET 4.0+ or as part of the Reactive Extension download or maybe even the TPL backport via NuGet. If you want you can use the following unoptimized variation of the class.
public class BlockingCollection<T>
{
private readonly Queue<T> m_Queue = new Queue<T>();
public void Add(T item)
{
lock (m_Queue)
{
m_Queue.Enqueue(item);
Monitor.Pulse(m_Queue);
}
}
public T Take()
{
lock (m_Queue)
{
while (m_Queue.Count == 0)
{
Monitor.Wait(m_Queue);
}
return m_Queue.Dequeue();
}
}
public bool TryTake(out T item)
{
item = default(T);
lock (m_Queue)
{
if (m_Queue.Count > 0)
{
item = m_Queue.Dequeue();
}
}
return item != null;
}
}
I think BlockingCollection would do better then Queue. Other then that, continuously checking queue size (and pausing the thread when its zero) is quite ok approach.
Btw, we are talking producer-consumer pattern here. I guess you can google it for some other approaches.

Weird C# Threading ThreadInterrupted exception

I am developing an application simulating a network comprising a number of nodes that exchange messages. I try to simulate the transmission channel with a Queue where every node can place a message. Then, another entity takes over the message and delivers it to the specified node. Then, i want to signal (with an event) the end of a transmission phase when the message queue is idle for a certain amount of time, say X, namely no new messages have been added to the queue for X mseconds.
I understand that my case follows the consumer/producer paradigm. So far, i have done the following:
public class Com<T>
{
private Thread dispatcher;
private Queue<T> queue;
private int waitTime;
private Object locker;
private Timer timer;
public event EventHandler EmptyQueueEvent;
public Com()
{
queue = new Queue<T>();
locker = new Object();
waitTime = X;
timer = new Timer(FireEmpty, null, Timeout.Infinite,Timeout.Infinite);
dispatcher = new Thread(Serve);
dispatcher.IsBackground = true;
dispatcher.Start();
}
private void Serve()
{
while (true)
{
try
{
if (queue.Count == 0)
{
timer.Change(waitTime, 0);
Thread.Sleep(Timeout.Infinite);
}
}
catch (ThreadInterruptedException)
{
}
while (queue.Count != 0)
{
lock (locker)
{
deliver(queue.Dequeue());
}
}
}
}
private void deliver(T item)
{
// Do stuff
}
public void Add(T item)
{
timer.Change(Timeout.Infinite, Timeout.Infinite);
lock (locker)
{
queue.Enqueue(item);
}
dispatcher.Interrupt();
}
private void FireEmpty(object o)
{
//Fire Event
}
}
However, running my simulations proves that my synchronization is not enough, since I am sometimes getting a "ThreadInterruptedException" while trying to dequeue my message (in method Serve()). Note that the exception does not occur each time i run the simulation, but rather rarely: approximately every 850-1000 executions (i am running the execution iteratively)..
Does anybody have an idea what it is wrong with my code? :)
Have you tried locking before you attempt to get the Queue count? Like:
private void Serve()
{
while (true)
{
try
{
int count = 0;
lock(locker)
count= queue.Count;
if (count == 0)
{
timer.Change(waitTime, 0);
Thread.Sleep(Timeout.Infinite);
}
}
catch (ThreadInterruptedException)
{
}
while (queue.Count != 0)
{
lock (locker)
{
deliver(queue.Dequeue());
}
}
}
}
It's possible that an add is getting called at the same time you're trying to count the number of items. Also, you might want to consider one of the collections from System.Collections.Concurrent if you're using .net 4.0.
** UPDATE **
I just took a closer look at your code and had an "Oh duh" moment. You should be getting a ThreadInterruptException because you're calling delegate.Interrupt(). Check the MSDN documentation on that. I think what you need to do is use something like a ManualResetEvent and instead of calling Interrupt() do a WaitOne() on that event.
** UPDATE2 **
Here's some sample code that includes my other locking suggestion as well (on Gist):
https://gist.github.com/1683547

C# once the main thread sleep, all thread stopped

I have a class running the Producer-Consumer model like this:
public class SyncEvents
{
public bool waiting;
public SyncEvents()
{
waiting = true;
}
}
public class Producer
{
private readonly Queue<Delegate> _queue;
private SyncEvents _sync;
private Object _waitAck;
public Producer(Queue<Delegate> q, SyncEvents sync, Object obj)
{
_queue = q;
_sync = sync;
_waitAck = obj;
}
public void ThreadRun()
{
lock (_sync)
{
while (true)
{
Monitor.Wait(_sync, 0);
if (_queue.Count > 0)
{
_sync.waiting = false;
}
else
{
_sync.waiting = true;
lock (_waitAck)
{
Monitor.Pulse(_waitAck);
}
}
Monitor.Pulse(_sync);
}
}
}
}
public class Consumer
{
private readonly Queue<Delegate> _queue;
private SyncEvents _sync;
private int count = 0;
public Consumer(Queue<Delegate> q, SyncEvents sync)
{
_queue = q;
_sync = sync;
}
public void ThreadRun()
{
lock (_sync)
{
while (true)
{
while (_queue.Count == 0)
{
Monitor.Wait(_sync);
}
Delegate query = _queue.Dequeue();
query.DynamicInvoke(null);
count++;
Monitor.Pulse(_sync);
}
}
}
}
/// <summary>
/// Act as a consumer to the queries produced by the DataGridViewCustomCell
/// </summary>
public class QueryThread
{
private SyncEvents _syncEvents = new SyncEvents();
private Object waitAck = new Object();
private Queue<Delegate> _queryQueue = new Queue<Delegate>();
Producer queryProducer;
Consumer queryConsumer;
public QueryThread()
{
queryProducer = new Producer(_queryQueue, _syncEvents, waitAck);
queryConsumer = new Consumer(_queryQueue, _syncEvents);
Thread producerThread = new Thread(queryProducer.ThreadRun);
Thread consumerThread = new Thread(queryConsumer.ThreadRun);
producerThread.IsBackground = true;
consumerThread.IsBackground = true;
producerThread.Start();
consumerThread.Start();
}
public bool isQueueEmpty()
{
return _syncEvents.waiting;
}
public void wait()
{
lock (waitAck)
{
while (_queryQueue.Count > 0)
{
Monitor.Wait(waitAck);
}
}
}
public void Enqueue(Delegate item)
{
_queryQueue.Enqueue(item);
}
}
The code run smoothly but the wait() function.
In some case I want to wait until all the function in the queue were finished running so I made the wait() function.
The producer will fire the waitAck pulse at suitable time.
However, when the line "Monitor.Wait(waitAck);" is ran in the wait() function, all thread stop, includeing the producer and consumer thread.
Why would this happen and how can I solve it? thanks!
It seems very unlikely that all the threads will actually stop, although I should point out that to avoid false wake-ups you should probably have a while loop instead of an if statement:
lock (waitAck)
{
while(queryProducer.secondQueue.Count > 0)
{
Monitor.Wait(waitAck);
}
}
The fact that you're calling Monitor.Wait means that waitAck should be released so it shouldn't prevent the consumer threads from locking...
Could you give more information about the way in which the producer/consumer threads are "stopping"? Does it look like they've just deadlocked?
Is your producer using Notify or NotifyAll? You've got an extra waiting thread now, so if you only use Notify it's only going to release a single thread... it's hard to see whether or not that's a problem without the details of your Producer and Consumer classes.
If you could show a short but complete program to demonstrate the problem, that would help.
EDIT: Okay, now you've posted the code I can see a number of issues:
Having so many public variables is a recipe for disaster. Your classes should encapsulate their functionality so that other code doesn't have to go poking around for implementation bits and pieces. (For example, your calling code here really shouldn't have access to the queue.)
You're adding items directly to the second queue, which means you can't efficiently wake up the producer to add them to the first queue. Why do you even have multiple queues?
You're always waiting on _sync in the producer thread... why? What's going to notify it to start with? Generally speaking the producer thread shouldn't have to wait, unless you have a bounded buffer
You have a static variable (_waitAck) which is being overwritten every time you create a new instance. That's a bad idea.
You also haven't shown your SyncEvents class - is that meant to be doing anything interesting?
To be honest, it seems like you've got quite a strange design - you may well be best starting again from scratch. Try to encapsulate the whole producer/consumer queue in a single class, which has Produce and Consume methods, as well as WaitForEmpty (or something like that). I think you'll find the synchronization logic a lot easier that way.
Here is my take on your code:
public class ProducerConsumer
{
private ManualResetEvent _ready;
private Queue<Delegate> _queue;
private Thread _consumerService;
private static Object _sync = new Object();
public ProducerConsumer(Queue<Delegate> queue)
{
lock (_sync)
{
// Note: I would recommend that you don't even
// bother with taking in a queue. You should be able
// to just instantiate a new Queue<Delegate>()
// and use it when you Enqueue. There is nothing that
// you really need to pass into the constructor.
_queue = queue;
_ready = new ManualResetEvent(false);
_consumerService = new Thread(Run);
_consumerService.IsBackground = true;
_consumerService.Start();
}
}
public override void Enqueue(Delegate value)
{
lock (_sync)
{
_queue.Enqueue(value);
_ready.Set();
}
}
// The consumer blocks until the producer puts something in the queue.
private void Run()
{
Delegate query;
try
{
while (true)
{
_ready.WaitOne();
lock (_sync)
{
if (_queue.Count > 0)
{
query = _queue.Dequeue();
query.DynamicInvoke(null);
}
else
{
_ready.Reset();
continue;
}
}
}
}
catch (ThreadInterruptedException)
{
_queue.Clear();
return;
}
}
protected override void Dispose(bool disposing)
{
lock (_sync)
{
if (_consumerService != null)
{
_consumerService.Interrupt();
}
}
base.Dispose(disposing);
}
}
I'm not exactly sure what you're trying to achieve with the wait function... I'm assuming you're trying to put some type of a limit to the number of items that can be queued. In that case simply throw an exception or return a failure signal when you have too many items in the queue, the client that is calling Enqueue will keep retrying until the queue can take more items. Taking an optimistic approach will save you a LOT of headaches and it simply helps you get rid of a lot of complex logic.
If you REALLY want to have the wait in there, then I can probably help you figure out a better approach. Let me know what are you trying to achieve with the wait and I'll help you out.
Note: I took this code from one of my projects, modified it a little and posted it here... there might be some minor syntax errors, but the logic should be correct.
UPDATE: Based on your comments I made some modifications: I added another ManualResetEvent to the class, so when you call BlockQueue() it gives you an event which you can wait on and sets a flag to stop the Enqueue function from queuing more elements. Once all the queries in the queue are serviced, the flag is set to true and the _wait event is set so whoever is waiting on it gets the signal.
public class ProducerConsumer
{
private bool _canEnqueue;
private ManualResetEvent _ready;
private Queue<Delegate> _queue;
private Thread _consumerService;
private static Object _sync = new Object();
private static ManualResetEvent _wait = new ManualResetEvent(false);
public ProducerConsumer()
{
lock (_sync)
{
_queue = new Queue<Delegate> _queue;
_canEnqueue = true;
_ready = new ManualResetEvent(false);
_consumerService = new Thread(Run);
_consumerService.IsBackground = true;
_consumerService.Start();
}
}
public bool Enqueue(Delegate value)
{
lock (_sync)
{
// Don't allow anybody to enqueue
if( _canEnqueue )
{
_queue.Enqueue(value);
_ready.Set();
return true;
}
}
// Whoever is calling Enqueue should try again later.
return false;
}
// The consumer blocks until the producer puts something in the queue.
private void Run()
{
try
{
while (true)
{
// Wait for a query to be enqueued
_ready.WaitOne();
// Process the query
lock (_sync)
{
if (_queue.Count > 0)
{
Delegate query = _queue.Dequeue();
query.DynamicInvoke(null);
}
else
{
_canEnqueue = true;
_ready.Reset();
_wait.Set();
continue;
}
}
}
}
catch (ThreadInterruptedException)
{
_queue.Clear();
return;
}
}
// Block your queue from enqueuing, return null
// if the queue is already empty.
public ManualResetEvent BlockQueue()
{
lock(_sync)
{
if( _queue.Count > 0 )
{
_canEnqueue = false;
_wait.Reset();
}
else
{
// You need to tell the caller that they can't
// block your queue while it's empty. The caller
// should check if the result is null before calling
// WaitOne().
return null;
}
}
return _wait;
}
protected override void Dispose(bool disposing)
{
lock (_sync)
{
if (_consumerService != null)
{
_consumerService.Interrupt();
// Set wait when you're disposing the queue
// so that nobody is left with a lingering wait.
_wait.Set();
}
}
base.Dispose(disposing);
}
}

Categories

Resources