Friday, December 03, 2004

statics and threads in java...

I was asked by someone recently about the evils of static members. I talked about lack of state in these variables, overriding being not possible, etc. But the other person asked me how statics were evil in the context of Threads. I told him that if a static method is synchronized, then only one static synchronized method in the class will be accessible at any point of time to the threads. He was still not convinced though. He told me that if a static synchronized method is accessed by a thread, then even non-static synchronized methods are not available to other threads.

I was surprised. My understanding of threads was that, if a method is synchronized, then the monitor of "this" has to be obtained by the calling thread before it enters that method. However, if the method is static then the monitor of the Class instance (this.class) has to be obtained. So if there were two threads and one of them is accessing a non-static synchronized method, and the other is accessing a static synchronized method, both threads should comfortably have access to those methods.

I tried out a sample. Here's the code for the same. Try out this sample and see for yourself.
Correct me if my understanding of threads is wrong.







public class StaticsAndThreadsTest
{
  public static void main(String[] args)
  {
      class Runner implements Runnable
      {
        TestObject obj = new TestObject("TestObject");
        private int code;
        public Runner(int i)
        {
          this.code = i;
        }

        public void run()
        {
          if(code%!= 0)
          {
            TestObject.staticallyDoingSomething();
            TestObject.staticallyDoingSomething();
          }
          else
          {
            obj.doSomething();
            obj.doSomething();
          }
        }
      };

    for(int i=0; i<10; i++)
    {
      Thread thrd = new Thread(new Runner(i));
      thrd.start();
    }
  }
}

class TestObject
{
  private String name;
  public TestObject(String name)
  {
    this.name = name;
  }

  public synchronized void doSomething()
  {
    System.out.println("Thread " + Thread.currentThread().getName() ": doing something.");
  }

  public static synchronized void staticallyDoingSomething()
  {
    try
    {
      System.out.println("Thread " + Thread.currentThread().getName() ": statically doing something.");
      Thread.sleep(1000);
    }
    catch(InterruptedException iex)
    {
    }

  }
}