I
incrediblesuperdude
Hi Everybody,
I have some understanding problems, about (thread) synchronization.
Hopefully somebody can explain it to me.
I have the following two processes that use the same piece of
hardware. However, they are not allowed to use it at the same time:
Process 1: System.Threading.Thread
Process 2: System.Timers.Timer elapsed event
I have taken two approaches to synchronize the access of these two
processes to the piece of hardware:
1. With Monitor.Enter(this) and Monitor.Exit(this) in a try-finally
block of the hardware code
2. With ManualResetEvent WaitOne(), Reset() and Set() also in a try-
finally block.
Both these methods could not prevent the hardware from getting called
twice.
My own theories why this doesn't work are:
1. Monitor synchronizes different Threads, but an elapsed event runs
on the same thread?
2. Two threads can both call WaitOne() at the same time, before one of
them had the chance to call Reset(). They will both then pass
WaitOne(), because the ManualResetEvent is for both still in the
signaled state.
'
I have written some test code to test situation 2 and indeed there
seems to be a possibility of no synchronization. I have posted the
code below.
Can anybody explain me why this happens, and how I can get a
synchronization for this?
Kind regards,
Gerben Heinen
### CODE ###
using System;
using System.Threading;
namespace ConsoleApplication3
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
public Class1(){}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Class1 c = new Class1();
c.Start();
}
private Thread thread1,thread2,thread3;
private ManualResetEvent mre = new ManualResetEvent(true);
private volatile int cntr = 0;
private Random random = new Random();
public void Start()
{
thread1 = new Thread(new ThreadStart(worker1));
thread2 = new Thread(new ThreadStart(worker2));
thread3 = new Thread(new ThreadStart(worker3));
thread1.Start();
thread2.Start();
thread3.Start();
}
private void worker1()
{
while(true)
{
try
{
Thread.Sleep(random.Next(100,1000));
mre.WaitOne();
mre.Reset();
// Console.WriteLine("worker1 started");
cntr++;
Thread.Sleep(random.Next(100,1000));
cntr--;
}
finally
{
mre.Set();
}
}
}
private void worker2()
{
while(true)
{
try
{
Thread.Sleep(random.Next(100,1000));
mre.WaitOne();
mre.Reset();
// Console.WriteLine("worker2 started");
cntr++;
Thread.Sleep(random.Next(100,1000));
cntr--;
}
finally
{
mre.Set();
}
}
}
private void worker3()
{
while(true)
{
if(cntr==2) System.Console.WriteLine("Cntr equals 2");
Thread.Sleep(10);
}
}
}
}
#######
I have some understanding problems, about (thread) synchronization.
Hopefully somebody can explain it to me.
I have the following two processes that use the same piece of
hardware. However, they are not allowed to use it at the same time:
Process 1: System.Threading.Thread
Process 2: System.Timers.Timer elapsed event
I have taken two approaches to synchronize the access of these two
processes to the piece of hardware:
1. With Monitor.Enter(this) and Monitor.Exit(this) in a try-finally
block of the hardware code
2. With ManualResetEvent WaitOne(), Reset() and Set() also in a try-
finally block.
Both these methods could not prevent the hardware from getting called
twice.
My own theories why this doesn't work are:
1. Monitor synchronizes different Threads, but an elapsed event runs
on the same thread?
2. Two threads can both call WaitOne() at the same time, before one of
them had the chance to call Reset(). They will both then pass
WaitOne(), because the ManualResetEvent is for both still in the
signaled state.
'
I have written some test code to test situation 2 and indeed there
seems to be a possibility of no synchronization. I have posted the
code below.
Can anybody explain me why this happens, and how I can get a
synchronization for this?
Kind regards,
Gerben Heinen
### CODE ###
using System;
using System.Threading;
namespace ConsoleApplication3
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
public Class1(){}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Class1 c = new Class1();
c.Start();
}
private Thread thread1,thread2,thread3;
private ManualResetEvent mre = new ManualResetEvent(true);
private volatile int cntr = 0;
private Random random = new Random();
public void Start()
{
thread1 = new Thread(new ThreadStart(worker1));
thread2 = new Thread(new ThreadStart(worker2));
thread3 = new Thread(new ThreadStart(worker3));
thread1.Start();
thread2.Start();
thread3.Start();
}
private void worker1()
{
while(true)
{
try
{
Thread.Sleep(random.Next(100,1000));
mre.WaitOne();
mre.Reset();
// Console.WriteLine("worker1 started");
cntr++;
Thread.Sleep(random.Next(100,1000));
cntr--;
}
finally
{
mre.Set();
}
}
}
private void worker2()
{
while(true)
{
try
{
Thread.Sleep(random.Next(100,1000));
mre.WaitOne();
mre.Reset();
// Console.WriteLine("worker2 started");
cntr++;
Thread.Sleep(random.Next(100,1000));
cntr--;
}
finally
{
mre.Set();
}
}
}
private void worker3()
{
while(true)
{
if(cntr==2) System.Console.WriteLine("Cntr equals 2");
Thread.Sleep(10);
}
}
}
}
#######