4

Background

The following code snippet is taken from a problem in, Visual C# 2005: How to Program, by Paul and Harvey Deitel (pp. 735). The code snippet is more or less an application for accessing data using 2 threads via a buffer (called shared). Just skip the code snippet, and look below if you would like a brief description of what is going on (before reading my question).

// Fig. 15.8: UnsynchronizedBufferTest.cs
// Showing multiple threads modifying a shared object without
// synchronization.
using System;
using System.Threading;

class UnsynchronizedBufferTest
{
    static void Main(string[] args)
    {
        // create shared object used by threads
        UnsynchronizedBufferTest shared = new UnsynchronizedBuffer();

        // Random object used by each thread
        Random random = new Random();

        // create Producer and Consumer objects 
        Producer producer = new Producer(shared, random);
        Consumer consumer = new Consumer(shared, random);

        // create threads for producer and consumer and set
        // delegates for each thread
        Thread producerThread =
            new Thread(new ThreadStart(producer.Produce));
        producerThread.Name = "Producer";

        Thread consumerThread =
            new Thread(new ThreadStart(consumer.Consume));
        consumerThread.Name = "Consumer";

        // start each thread
        producerThread.Start();
        consumerThread.Start();
    } // end Main
} // end class UnsynchronizedBufferTest

Just for the basic idea of what is going on here, a producer thread is running that puts data into a buffer (called shared). Also, a consumer thread is running that gets the data from the buffer.

The Producer and Consumer objects are somehow sharing this buffer, which is what I am having trouble understanding. From what I have always understood about the C# language, when an object is passed to a method, it is only a copy or instance that actually gets passed. I guess that must be wrong, because when the Producer puts the data in the buffer, the Consumer sees it...

The code snippet for the buffer (in case anyone needs that) is as follows (pp. 734). Honestly I don't think it will have anything to do with the answer, and that the answer has more to do with the C# language because really all this class represents is an integer.

// Fig. 15.7: UnsynchronizedBuffer.cs
// An unsynchronized shared buffer implementation.
using System;
using System.Threading;

// this class represents a single shared int
public class UnsynchronizedBuffer : Buffer
{
    // buffer shared by producer and consumer threads
    private int buffer = -1;

    // property buffer
    public int Buffer
    {
        get
        {
            Console.WriteLine("{0} reads {1}",
                Thread.CurrentThread.Name, buffer);
            return buffer;
        } // end get
        set
        {
            Console.WriteLine("{0} writes {1}",
                Thread.CurrentThread.Name, value);
            buffer = value;
        } // end set
    } // end property Buffer
} // end class UnsynchronizedBuffer

Question

How is it that both objects (the Producer and the Consumer) are able to see the changes that each other makes? (i.e. when the Producer sets the data, the Consumer can see the new data)

I must be missing something in my fundamental understanding of C#.

  • C# (and Java) do not copy object types when passing parameters, only the object reference is copied. However, if they did, they wouldn't make a deep copy in any case. To prevent sharing in this example, not only would a copy of the objects (Producer/Consumer) be required but a deep copy at that (of course, the language does neither shallow nor deep copying here). FWIW, local variable assignment works the same as parameter passing, i.e. two local variables can refer to the same object, whether they are in the same method or not... – Erik Eidt May 23 '16 at 23:17
  • Hopefully what follows in the book is how shared objects are manipulated by multiple threads with synchronization. – dbasnett May 23 '16 at 23:53
  • @dbasnett Yeah... 15.7 Producer/Consumer Relationship with Thread Synchronization :) – Snoop May 23 '16 at 23:56
4

From what I have always understood about the C# language, when an object is passed to a method, it is only a copy or instance that actually gets passed.

That's where you are getting mixed up.

All variables in C# are references to objects. The buffer object in your example lives on the heap, and both the consumer and producer have a reference to that object.

When you pass a variable to a function, you are creating a copy of the reference, but the new reference still points to the same object on the heap. Therefore, both the consumer and producer are modifying the same object.

  • 1
    @StevieV: While there are rules that govern whether a variable is created on the heap or on the stack, the .NET and C# specifications consider this an implementation detail. More info here. – Robert Harvey May 23 '16 at 23:37
  • 1
    Value types (i.e. primitive types and some structs) have value semantics in C#. Variables containing value types point to the value, not a reference. Assigning a value to a variable or formal parameter copies the value, not the reference. Modifying such a value in a method leaves the original passed-in variable intact. See msdn.microsoft.com/en-us/library/s1ax56ch.aspx. cc: @StevieV – Robert Harvey May 23 '16 at 23:44
  • 1
    @StevieV: Reference types don't work that way. If you pass a variable holding a reference type into a method parameter, and then modify the object pointed to by that parameter, the original object in the original variable is modified, because the method parameter references the same object as the original variable. See msdn.microsoft.com/en-us/library/490f96s2.aspx – Robert Harvey May 24 '16 at 0:12
  • 1
    So now you know the whole scoop. – Robert Harvey May 24 '16 at 0:13
  • 1
    @RobertHarvey As for the first article you posted here in the comments, I feel like Mandy Patinkin in Princess Bride whenever the guy says implementation details. – Snoop May 24 '16 at 0:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.