0

This is a bit of a stupid question, but here goes.

I'm programming a lightswitch (a group semaphore). It works by passing a static semaphore into the lightswitch constructor. When a thread calls the acquire method on the lightswitch, it acquires the semaphore. I have, say, four threads, two acquire the lightswitch, two acquire the semaphore. The first lightswitch thread acquires the lightswitch, thus acquiring the semaphore. This blocks the two threads who try to acquire the semaphore, but the other thread that acquires the lightswitch can go through. The two trying to acquire the semaphore are blocked until the last thread in the lightswitch is finished.

Here's some code to demonstrate this:

Test class with the static semaphore, declaring the lightswitch.

class TestLightSwitch
    {

        private static Utilities.LightSwitch ls;
        private static Utilities.Semaphore sem = new Utilities.Semaphore();

        static void Main(string[] args)
        {

            sem.Release();

            ls = new SeansConcurrencyUtilities.LightSwitch(sem);

Lightswitch has a copy of the semaphore:

 public class LightSwitch
    {

        private readonly Utilities.Semaphore sem;

        public LightSwitch(Semaphore s)
        {

            sem = s;

What I don't understand is why it works. Why is it that thread a, goes into the lightswitch, acquires the lightswitch's copy of the semaphore, and that affects the original semaphore, so when thread b acquires the original semaphore, it's blocked? It seems to be like pass by reference or something.

SlashThingy
  • 177
  • 2
  • 12

1 Answers1

3

Why is it that thread a, goes into the lightswitch, acquires the lightswitch's copy of the semaphore, and that affects the original semaphore, so when thread b acquires the original semaphore, it's blocked? It seems to be like pass by reference or something.

Since Semaphore is a reference type (a class), not a value type (a struct), a copy of the reference to the Semaphore object is being passed to the LightSwitch constuctor. The object itself is never copied.

Lightswitch has a copy of the semaphore:

As follows, both LightSwitch.sem and TestLightSwitch.sem fields point to the same semaphore.

dcastro
  • 66,540
  • 21
  • 145
  • 155
  • 1
    By default, all parameters are passed by value. This is irrespective of the type (value or reference). There is a difference though, a reference type will get its reference copied, and not the data. As there is no `ref` modifier used in code, your answer is technically incorrect, even though the behaviour you describe might be true. – oleksii May 26 '14 at 09:00
  • @oleksii The definition of "pass by reference" and "pass by value" tend to be a little loose. By "it is being passed by reference", I meant that a reference to the actual `Semaphore` object is being passed to the ctor, in such a way that `LightSwitch` and `TestLightSwitch` will be referencing the same object, which is technically correct. In short, I'm using a definition similar to this one: http://stackoverflow.com/a/430958/857807 – dcastro May 26 '14 at 09:23
  • @dcastro: Unless you use oleksii's definition, it's hard to clearly articulate the 4 possible passing scenarios in C#. 1) Ref type by value, 2) Ref type by ref, 3) Value type by value, 4) Value type by ref. How do you distinguish between (1), (2) and (4) if they're all just 'pass by ref'? It's much clearer if you separate what the object *is* (value or ref *type*) from how it's *passed* (*by* value or *by* reference). – Baldrick May 26 '14 at 09:42
  • @Baldrick fair enough. I've edited my answer, it should be clearer now. – dcastro May 26 '14 at 10:03