C# threading - Lock Object

21,095

Solution 1

You need to create a separate lock object. The problem is that you re-assign t_x inside the loop. Assuming thread b1 gets inside the loop before b2 gets to the lock statement, b2 will be allowed inside the lock statement because, by that time, t_x will be a new object that does not have a lock on it.

Solution 2

No, you can't do this - the lock block is shorthand for the following:

try(Monitor.Enter(lockObject))
{
    //critical section
}
finally
{
    Monitor.Exit(lockObject)
}

The documentation for Monitor.Enter states, "Use Monitor to lock objects (that is, reference types), not value types. When you pass a value type variable to Enter, it is boxed as an object. If you pass the same variable to Enter again, it is boxed as a separate object, and the thread does not block"

Solution 3

The lock (t_x) call boxes an integer as a temporary object. Each call to lock(t_x) creates a New object and locking is useless.

(Lock expects an object and creates a NEW temporary object from the integer)

Just create a seperate lock object like said above by Femaref.

Solution 4

You have to use an extra object for the lock

object lockObj = new object();
public void foo()
{
    lock(lockObj)
    {
    //do stuff here
    }
}
Share:
21,095
paul simmons
Author by

paul simmons

Updated on March 26, 2020

Comments

  • paul simmons
    paul simmons about 4 years

    I am trying to lock a "boxed" object in a c# app, is this not possible?

        class t
        {
            System.Object t_x = new object();
    
            public t(int p)
            {
                t_x = p;
    
            }
    
            public void w()
            {
                lock (t_x)
                {
                    for (int i = 0; i < 4; i++)
                    {
    
                        {
                            t_x = ((int)t_x) + 1;
                            Console.WriteLine(t_x);
                            Thread.Sleep(1000);
                        }
                    }
                }
            }
        }
    

    In another class I can start 2 threads:

            Thread b1 = new Thread(new ThreadStart(t1.w));
            b1.Start();
            Thread b2 = new Thread(new ThreadStart(t1.w));
            b2.Start();
    

    However the portion is not locked. When I lock an arbitrary object (i.e. one created and not modified as object a=new object()) it locks well. Is boxing operation somehow "depromotes" my Object??

  • Cédric Boivin
    Cédric Boivin almost 15 years
    That the good way to do it. It's in the first exam 70-536 of microsoft certification.
  • Cédric Boivin
    Cédric Boivin almost 15 years
    I think Monitor it's a better way to do that
  • Daniel Earwicker
    Daniel Earwicker almost 15 years
    @Cedric - read Lee's answer more carefully. The lock statement is exactly the same as using Monitor.Enter and Monitor.Exit. It's just a neater syntax for the same pattern. The issue is not whether to use lock or Monitor (not really a choice, as they are the same). The issue is to always pass the same object to serve as the lock, which is broken if you use a value type as it is boxed differently ever time you access it.
  • Daniel Earwicker
    Daniel Earwicker almost 15 years
    This is the right answer - not because of the code snippet (the lock statement is fine) but because it mentions the difference between value and reference types. A value type is boxed again each time it is converted to the universal object base class, so it can't reliably act as the locking target. So this is better than the accepted answer.
  • Seng Cheong
    Seng Cheong about 12 years
    While I wouldn't recommend doing it this way (just use another object to lock on), I don't understand the downvotes, as it is correct.