title: Why can threads change instance data if it is blocked in another thread?
body: <p>I began to study lock and immediately a question arose.</p>
  <p>It <a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/statements/lock" rel="nofollow noreferrer">docs.microsoft</a> says here:</p>
  <blockquote>
  <p>The lock statement acquires the mutual-exclusion lock for a given
  object, executes a statement block, and then releases the lock. While
  a lock is held, the thread that holds the lock can again acquire and
  release the lock. <strong>Any other thread is blocked from acquiring the lock
  and waits until the lock is released</strong>.</p>
  </blockquote>
  <p>I made a simple example proving that another thread with a method without the lock keyword can easily change the data of an instance while that instance is occupied by a method using the lock from the first thread. It is worth removing the comment from the blocking and the work is done as expected. I thought that a lock would block access to an instance from other threads, even if they don't use a lock on that instance in their methods.</p>
  <p><strong>Questions</strong>:</p>
  <ol>
  <li><p>Do I understand correctly that locking an instance on one thread allows data from another thread to be modified on that instance, unless that other thread also uses that instance's lock? If so, what then does such a blocking generally give and why is it done this way?</p>
  </li>
  <li><p>What does this mean in simpler terms? <strong>While a lock is held, the thread that holds the lock can again acquire and release the lock</strong>.</p>
  </li>
  </ol>
  <hr />
  <blockquote>
  <p>So code formatting works well.</p>
  </blockquote>
  <hr />
  <pre><code>using System;
  using System.Threading;
  using System.Threading.Tasks;
  
  namespace ConsoleApp1
  {
      class A
      {
          public int a;
      }
  
      class Program
      {
          static void Main(string[] args)
          {
              A myA = new A();
  
              void MyMethod1()
              {
                  lock (myA)
                  {
                      for (int i = 0; i &lt; 10; i++)
                      {
                          Thread.Sleep(500);
                          myA.a += 1;
                          Console.WriteLine($&quot;Work MyMethod1 a = {myA.a}&quot;);
                      }
                  }                               
              }
  
              void MyMethod2()
              {
                  //lock (myA)
                  {
                      for (int i = 0; i &lt; 10; i++)
                      {
                          Thread.Sleep(500);
                          myA.a += 100;
                          Console.WriteLine($&quot;Work MyMethod2 a = {myA.a}&quot;);
                      }
                  }                
              }
  
              Task t1 = Task.Run(MyMethod1);
              Thread.Sleep(100);
              Task t2 = Task.Run(MyMethod2);
  
              Task.WaitAll(t1, t2);
  
          }
      }
  }
  </code></pre>