Monitor class not working as specified

  • Thread starter Thread starter I.Benc
  • Start date Start date
I

I.Benc

Hi!

I have trouble with the Monitor class.
I did some troubleshooting and finally figured out the
problem. The thing is, the Monitor class simple does not work
as specified.
Better said, if used by the framework through lock( obj ) statements
it works fine, however if used through Monitor.Enter( obj ) and
Monitor.Exit( obj), deadlocks can occur.

Here is a simple example that shows this behavior. If the example
is run as specified everything is fine. If the lock statements are
commented, and Enter & Exit statements uncommented deadlock occurs.

Why this happens? .NET framework help specifies that this should be
the same. I found in the help, that Monitor maintains Waiting and
Ready
queues of threads for each object, but I haven't found the clear
explanation
of the meanings of this queues.

Any sugestions?



using System;
using System.Threading;
namespace ConsoleApplication4
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
string s;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Class1 c1 = new Class1();
Thread t1 = new Thread( new ThreadStart( c1.f1 ));
Thread t2 = new Thread( new ThreadStart( c1.f2 ));

t1.Start();
t2.Start();
t1.Join();
t2.Join();
Console.ReadLine();
}

public Class1()
{
s = "0";
}

void f1()
{
lock( s )
{
//Monitor.Enter( s );
broj = (Convert.ToInt32( s ) + 1).ToString();
Console.WriteLine( s );
//Monitor.Exit( s );
}
}

void f2()
{
lock( s )
{
//Monitor.Enter( s );
broj = (Convert.ToInt32( s ) + 1).ToString();
Console.WriteLine( s );
//Monitor.Exit( s );
}
}

}
}
 
A lock(ref) is exactly like Monitor.Enter/Exit, proctected by try/finally.
You can verify this with ILDASM.

The code you posted won't compile. After fixing the compilation error, your
code works as expected, if I make some assumptions:

void f1()
{
Monitor.Enter( s );
(Convert.ToInt32( s ) + 1).ToString();
Console.WriteLine( s );
Monitor.Exit( s );
}

Note however, that the code fragment below will lead to a deadlock, since
the Monitor.Exit() is called for a different object reference than the
Monitor.Enter():


void f1()
{
Monitor.Enter( s );
s = (Convert.ToInt32( s ) + 1).ToString();
Console.WriteLine( s );
Monitor.Exit( s );
}

Strings are immutable. Modifying a string creates a new string. Worse,
modifying a string may return an instance of an existing interned string,
which is why lock or Monitor.Enter is a very bad idea on strings.
 
Back
Top