Java programozók körében elterjedt tévhit, hogy a synchronized módosítóval ellátott metódusok vagy blokkok által bezárt programsorokat csak egy szál futtathatja egy időben. A valóság az, hogy a kérdéses osztály példányaira vonatkozik a synchronized, ha az osztályból van kettő példányunk, amelyek egy közös static változót használnának, akkor mit sem ér a synchronized... Hogy ne a levegőbe beszéljek, nézzünk egy konkrét példát, vegyünk például egy osztályt, amelynek egy statikus változója és két metódusa van:

public class Test
{
  private static Integer counter=0;
 
  public synchronized void addToCounter(Integer number)
  {
    counter += number;
  }
 
  public Integer getCounter()
  {
    return counter;
  }
}

Láthatjuk, hogy az addToCounter metódus szinkronizált blokkban van, így azt a counter nevű változóhoz több szál nem férhet hozzá:

public class ThreadA implements Runnable
{
  @Override
  public void run()
  {
    try
    {
      Test test = new Test();
      for (int count = 0; count < 100; count++)
      {
        test.addToCounter(1);
        Thread.sleep(7);
      }
      System.out.println(test.getCounter());
    } catch (InterruptedException ex)
    {
      Logger.getLogger(ThreadA.class.getName()).log(Level.SEVERE, ex.toString(), ex);
    }
  }
}

Ahogy fentebb látszik, létrehoztunk egy ThreadA (és egy ThreadB) osztályt, amelyekkel több szálon tudjuk futtatni a Test osztály "szálbiztos" addToCounter metódusát:

public class Main
{
  public Main()
  {
    ThreadA a=new ThreadA();
    ThreadB b=new ThreadB();
   
    new Thread(a).start();
    new Thread(b).start();
  }
 
  public static void main(String[] args)
  {
    new Main();
  }
}

Az eremény meglepő lehet:

197
198

Elvileg az eremény 200 kellene lennie az utolsónak lefutó szál esetén, hiszen minden hozzáadás szinkronizált volt... azonban a synchronized két külön példányra volt értelmezett, így a statikus változót két szál akár egyidőben is módosíthatta. A fent vázolt probléma abból a tényból adódik, hogy a synchronized módosítóval jelölt metódus (lásd fentebb) az alábbi kóddal lesz azonos:

public void addToCounter(Integer number)
{
  synchronized (this)
  {
    counter += number;
  }
}

Ahogy a kódból is kiolvasható: a kód szálzárása példány szintű lesz (this), s ebből adódóan csak akkor jön elő a probléma, ha statikus változót akarunk egy nem statikus - de szinkronizált metódusból elérni. A megoldás egyszerű, kell készítenünk egy statikus és szinkronizált metódust, vagy osztály szintű szálzárást állítunk be:

public void addToCounter(Integer number)
{
  synchronized (getClass())
  {
    counter += number;
  }
}

Érdemes figyelni ilyen apróságokra, hiszen egy többszálú programban hibát keresni nem egyszerű, s egy tévhit még nehezebbé teheti a hiba okának felderítését.