Listing 2

using namespace System;
using namespace System::Threading;

public ref class Point
{
  int x;
  int y;
public:

// define read-write instance properties X and Y

  property int X
  {
    int get() { return x; }
    void set(int val) { x = val; }
  }

  property int Y
  {
    int get() { return y; }
    void set(int val) { y = val; }
  }

  // ...

  void Move(int xor, int yor) 
  {
/*1a*/    Monitor::Enter(this);
    X = xor;
    Y = yor;
/*1b*/    Monitor::Exit(this);
  } 

  virtual bool Equals(Object^ obj) override
  {

    // ...

    if (GetType() == obj->GetType())
    {
      int xCopy1, xCopy2, yCopy1, yCopy2;
      Point^ p = static_cast<Point^>(obj);

/*2a*/      Monitor::Enter(this);
      xCopy1 = X;
      xCopy2 = p->X;
      yCopy1 = Y;
      yCopy2 = p->Y;
/*2b*/      Monitor::Exit(this);

      return (xCopy1 == xCopy2) && (yCopy1 == yCopy2);
    }

    return false;
  }

  virtual int GetHashCode() override
  {
    int xCopy;
    int yCopy;

/*3a*/    Monitor::Enter(this);
    xCopy = X;
    yCopy = Y;
/*3b*/    Monitor::Exit(this);
    return xCopy ^ (yCopy << 1);
  }

  virtual String^ ToString() override
  {
    int xCopy;
    int yCopy;

/*4a*/    Monitor::Enter(this);
    xCopy = X;
    yCopy = Y;
/*4b*/    Monitor::Exit(this);

    return String::Concat("(", xCopy, ",", yCopy, ")");
  }
};

public ref class ThreadY
{
  Point^ pnt;
  bool mover;
public:
  ThreadY(bool isMover, Point^ p)
  {
    mover = isMover;
    pnt = p;
  }

  void StartUp()
  {
    if (mover)
    {
      for (int i = 1; i <= 10000000; ++i)
      {
/*1*/       pnt->Move(i, i);
      }
    }
    else
    {
      for (int i = 1; i <= 10; ++i)
      {
/*2*/       Console::WriteLine(pnt); // calls ToString
        Thread::Sleep(10);
      }
    }
  }
};

int main()
{
  Point^ p = gcnew Point;

/*1*/ ThreadY^ o1 = gcnew ThreadY(true, p);
/*2*/ Thread^ t1 = gcnew Thread(gcnew ThreadStart(o1, &ThreadY::StartUp));

/*3*/ ThreadY^ o2 = gcnew ThreadY(false, p);
/*4*/ Thread^ t2 = gcnew Thread(gcnew ThreadStart(o2, &ThreadY::StartUp));

  t1->Start();
  t2->Start();

  Thread::Sleep(100);
/*5*/ Console::WriteLine("x: {0}", p->X);
/*6*/ Console::WriteLine("y: {0}", p->Y);

/*7*/ t1->Join();
  t2->Join();
}