using lock

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • marvind

    using lock

    Hello,

    Why doesn't the lock in Class2::Execute protect the critical section:

    public Class1
    {
    ...
    public DataTable SchemaTable = new DataTable();
    }

    Class1 creates many instances of Class2 and calls the corresponding
    Execute function on different threads.

    public Class2
    {
    ...
    public void Execute()
    {

    // sync multiple threads - ensure only one thread obtains the
    schema table
    // does not really work, many threads enter this section at the
    same time.
    lock (_parent.Schema Table)
    {
    if (0 == _parent.SchemaT able.Count)
    {
    _parent.SchemaT able = rdr.GetSchemaTa ble(); // returns a new
    DataTable
    }
    }
    ...
    }
    ...
    }

    I think the problem is that rdr.GetSchemaTa ble returns a new DataTable
    that _parent.SchemaT able points at but I am not really clear how the
    ..NET internals work. I am able to get around this problem by using a
    dedicated SyncLock object.

    I would appreciate if someone could point out clearly why the code
    should not be expected to work.

    Thanks

  • Nicholas Paldino [.NET/C# MVP]

    #2
    Re: using lock

    marfind,

    Yeah, this is definitely not good. A lock statement basically compiles
    to the following:

    // If you use lock (this) ;
    Montior.Enter(t his);

    try
    {
    }
    finally
    {
    Monitor.Exit(th is);
    }

    So, by changing the contents of the reference that was passed to enter,
    you never actually release the lock. In effect, you are allocating all of
    these locks, which are never released, but every time you make a call, you
    change the value of what is locked on the next call. That's why it never
    works.

    I'm surprized the compiler didn't catch this (it could be because you
    are locking on something that is returned from the object).

    In the end, you are on the right track, using a dedicated sync lock
    object for the lock.

    Hope this helps.


    --
    - Nicholas Paldino [.NET/C# MVP]
    - mvp@spam.guard. caspershouse.co m


    "marvind" <marvind434@yah oo.com> wrote in message
    news:1126100990 .973893.22190@o 13g2000cwo.goog legroups.com...[color=blue]
    > Hello,
    >
    > Why doesn't the lock in Class2::Execute protect the critical section:
    >
    > public Class1
    > {
    > ...
    > public DataTable SchemaTable = new DataTable();
    > }
    >
    > Class1 creates many instances of Class2 and calls the corresponding
    > Execute function on different threads.
    >
    > public Class2
    > {
    > ...
    > public void Execute()
    > {
    >
    > // sync multiple threads - ensure only one thread obtains the
    > schema table
    > // does not really work, many threads enter this section at the
    > same time.
    > lock (_parent.Schema Table)
    > {
    > if (0 == _parent.SchemaT able.Count)
    > {
    > _parent.SchemaT able = rdr.GetSchemaTa ble(); // returns a new
    > DataTable
    > }
    > }
    > ...
    > }
    > ...
    > }
    >
    > I think the problem is that rdr.GetSchemaTa ble returns a new DataTable
    > that _parent.SchemaT able points at but I am not really clear how the
    > .NET internals work. I am able to get around this problem by using a
    > dedicated SyncLock object.
    >
    > I would appreciate if someone could point out clearly why the code
    > should not be expected to work.
    >
    > Thanks
    >[/color]


    Comment

    • marvind

      #3
      Re: using lock

      yes, it does help. Thank you.

      Comment

      • Jon Skeet [C# MVP]

        #4
        Re: using lock

        Nicholas Paldino [.NET/C# MVP] <mvp@spam.guard .caspershouse.c om> wrote:[color=blue]
        > Yeah, this is definitely not good. A lock statement basically compiles
        > to the following:
        >
        > // If you use lock (this) ;
        > Montior.Enter(t his);
        >
        > try
        > {
        > }
        > finally
        > {
        > Monitor.Exit(th is);
        > }
        >
        > So, by changing the contents of the reference that was passed to enter,
        > you never actually release the lock.[/color]

        No, that's not true.

        According to the spec:

        <quote>
        A lock statement of the form

        lock (x) ...

        where x is an expression of a reference-type, is precisely equivalent
        to

        System.Threadin g.Monitor.Enter (x);
        try {
        ...
        }
        finally {
        System.Threadin g.Monitor.Exit( x);
        }

        except that x is only evaluated once.
        </quote>

        Note the "x is only evaluated once" bit.

        The lock is correctly released, but it won't be the same lock that is
        acquired by the next call.

        --
        Jon Skeet - <skeet@pobox.co m>
        Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

        If replying to the group, please do not mail me too

        Comment

        Working...