Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. The Weird and The Wonderful
  4. Unsafe locking

Unsafe locking

Scheduled Pinned Locked Moved The Weird and The Wonderful
tutorialdiscussionannouncement
7 Posts 6 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Member 2053006
    wrote on last edited by
    #1

    I just refactored this:

    if (requiresLocking)
    {
    Monitor.Enter(lockerObject);
    }

    // Lots of (ahem, good) code here.

    if (requiresLocking)
    {
    Monitor.Exit(lockerObject);
    }

    Where requiresLocking is a variable passed in to the function. Into this:

    object thisLocker = new object();
    if (requiresLocking)
    {
    thisLocker = lockerObject;
    }
    lock (thisLocker)
    {
    // Lots of (ahem, good) code here.
    }

    I am afraid that the original version was my own code and I am still not happy with the modified version. Second thoughts: on looking at requiresLocking it will be true except in rare and unusual conditions (for example the application or windows is crashing.) In those conditions I can accept the extra delay of acquiring a lock :-) I changed it to:

    lock (lockerObject)
    {
    // Lots of (ahem, good) code here.
    }

    P R L 3 Replies Last reply
    0
    • M Member 2053006

      I just refactored this:

      if (requiresLocking)
      {
      Monitor.Enter(lockerObject);
      }

      // Lots of (ahem, good) code here.

      if (requiresLocking)
      {
      Monitor.Exit(lockerObject);
      }

      Where requiresLocking is a variable passed in to the function. Into this:

      object thisLocker = new object();
      if (requiresLocking)
      {
      thisLocker = lockerObject;
      }
      lock (thisLocker)
      {
      // Lots of (ahem, good) code here.
      }

      I am afraid that the original version was my own code and I am still not happy with the modified version. Second thoughts: on looking at requiresLocking it will be true except in rare and unusual conditions (for example the application or windows is crashing.) In those conditions I can accept the extra delay of acquiring a lock :-) I changed it to:

      lock (lockerObject)
      {
      // Lots of (ahem, good) code here.
      }

      P Offline
      P Offline
      PIEBALDconsult
      wrote on last edited by
      #2

      Member 2053006 wrote:

      object thisLocker = new object();

      I hope that isn't a local variable. (It needs to be a field.)

      1 Reply Last reply
      0
      • M Member 2053006

        I just refactored this:

        if (requiresLocking)
        {
        Monitor.Enter(lockerObject);
        }

        // Lots of (ahem, good) code here.

        if (requiresLocking)
        {
        Monitor.Exit(lockerObject);
        }

        Where requiresLocking is a variable passed in to the function. Into this:

        object thisLocker = new object();
        if (requiresLocking)
        {
        thisLocker = lockerObject;
        }
        lock (thisLocker)
        {
        // Lots of (ahem, good) code here.
        }

        I am afraid that the original version was my own code and I am still not happy with the modified version. Second thoughts: on looking at requiresLocking it will be true except in rare and unusual conditions (for example the application or windows is crashing.) In those conditions I can accept the extra delay of acquiring a lock :-) I changed it to:

        lock (lockerObject)
        {
        // Lots of (ahem, good) code here.
        }

        R Offline
        R Offline
        Robert Rohde
        wrote on last edited by
        #3

        How about this:

        public void OriginalMethod(bool requiresLocking, object otherParams)
        {
        if (requiresLocking)
        {
        lock (lockerObject)
        {
        LotsOfCodeMovedToNewMethod(otherParams);
        }
        }
        else
        {
        LotsOfCodeMovedToNewMethod(otherParams);
        }
        }

        L 1 Reply Last reply
        0
        • R Robert Rohde

          How about this:

          public void OriginalMethod(bool requiresLocking, object otherParams)
          {
          if (requiresLocking)
          {
          lock (lockerObject)
          {
          LotsOfCodeMovedToNewMethod(otherParams);
          }
          }
          else
          {
          LotsOfCodeMovedToNewMethod(otherParams);
          }
          }

          L Offline
          L Offline
          Lost User
          wrote on last edited by
          #4

          I would not do that. Conditional locking controlled by a parameter would introduce a nasty possibility for bugs. If this method is called from many different places it would be hard to ensure that requiresLocking is indeed set to the right value. If there is a way to determine this in the method itself we would not need this parameter. If the method workes with data that is shared between threads, then it should always be locked. Conditional locking very probably so little a benefit that it's not worth the possible bug hunt.

          I'm invincible, I can't be vinced

          1 Reply Last reply
          0
          • M Member 2053006

            I just refactored this:

            if (requiresLocking)
            {
            Monitor.Enter(lockerObject);
            }

            // Lots of (ahem, good) code here.

            if (requiresLocking)
            {
            Monitor.Exit(lockerObject);
            }

            Where requiresLocking is a variable passed in to the function. Into this:

            object thisLocker = new object();
            if (requiresLocking)
            {
            thisLocker = lockerObject;
            }
            lock (thisLocker)
            {
            // Lots of (ahem, good) code here.
            }

            I am afraid that the original version was my own code and I am still not happy with the modified version. Second thoughts: on looking at requiresLocking it will be true except in rare and unusual conditions (for example the application or windows is crashing.) In those conditions I can accept the extra delay of acquiring a lock :-) I changed it to:

            lock (lockerObject)
            {
            // Lots of (ahem, good) code here.
            }

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #5

            Your last version is the simplest and probably the best. Conditional locking with the help of a boolean parameter would only introduce an external source of bugs while (probably) bringing only unnoticably more performance. What you really should take a look at is the 'Lots of (ahem, good) code here' part. Holding a lock for a longer time may reduce the benefits of working with several threads to zero. You may end up with the performance of a single threaded application. Breaking up the code, identifying smaller critical sections and using several short locks in those locations may help a lot. I have worked on my own UI. There is an application thread, which of course often makes changes to the controls or their properties, and there is a rendering thread to draw the UI. Not synchronizing those two threads leads to ugly graphical effects when the rendering thread catches the application thread in the middle of some changes. Now I could simply lock the entire control tree when rendering or when making changes to the UI. This would work, but one thread would come to a complete halt when the other one is doing something. Instead, I never lock the entire tree, but only the one control that is currently going to be rendered or changed. One huge lock has been replaced by many brief locks. This way the two threads collide far less often (only when they happen to access the same control) and if they do, then the wait for the other thread is only brief. Locking is always a manner of 'as much as needed and as little as possible'.

            I'm invincible, I can't be vinced

            J 1 Reply Last reply
            0
            • L Lost User

              Your last version is the simplest and probably the best. Conditional locking with the help of a boolean parameter would only introduce an external source of bugs while (probably) bringing only unnoticably more performance. What you really should take a look at is the 'Lots of (ahem, good) code here' part. Holding a lock for a longer time may reduce the benefits of working with several threads to zero. You may end up with the performance of a single threaded application. Breaking up the code, identifying smaller critical sections and using several short locks in those locations may help a lot. I have worked on my own UI. There is an application thread, which of course often makes changes to the controls or their properties, and there is a rendering thread to draw the UI. Not synchronizing those two threads leads to ugly graphical effects when the rendering thread catches the application thread in the middle of some changes. Now I could simply lock the entire control tree when rendering or when making changes to the UI. This would work, but one thread would come to a complete halt when the other one is doing something. Instead, I never lock the entire tree, but only the one control that is currently going to be rendered or changed. One huge lock has been replaced by many brief locks. This way the two threads collide far less often (only when they happen to access the same control) and if they do, then the wait for the other thread is only brief. Locking is always a manner of 'as much as needed and as little as possible'.

              I'm invincible, I can't be vinced

              J Offline
              J Offline
              Julien Villers
              wrote on last edited by
              #6

              Very good explanation and clear example :thumbsup:

              'As programmers go, I'm fairly social. Which still means I'm a borderline sociopath by normal standards.' Jeff Atwood 'I'm French! Why do you think I've got this outrrrrageous accent?' Monty Python and the Holy Grail

              G 1 Reply Last reply
              0
              • J Julien Villers

                Very good explanation and clear example :thumbsup:

                'As programmers go, I'm fairly social. Which still means I'm a borderline sociopath by normal standards.' Jeff Atwood 'I'm French! Why do you think I've got this outrrrrageous accent?' Monty Python and the Holy Grail

                G Offline
                G Offline
                greldak
                wrote on last edited by
                #7

                don't forget to check that your current process owns the lock after setting it - another process may have locked it between you checking if its locked and you locking it

                1 Reply Last reply
                0
                Reply
                • Reply as topic
                Log in to reply
                • Oldest to Newest
                • Newest to Oldest
                • Most Votes


                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • World
                • Users
                • Groups