Главная

Java

Многопоточность


synchronized.

синхронизированый блок кода может быть выполнен только одним потоком одновременно !!!


блокировка на уровне метода:


public class DemoClass{
    public synchronized void demoMethod(){
    //other thread safe code
    }
}



блокировка на уровне статического метода:

В статическом методе, синхронизация будет осуществляться по классу.


public class DemoClass{
    public static synchronized void demoMethod(){
    //other thread safe code
    }
}



блокировка на уровне обьекта:

опасная штука !!!

Не синхронизируйте по не финальному (no final) полю, потому что ссылка, на не финальное поле может измениться в любое время, а затем другой поток может получить синхронизацию на разных объектах и уже не будет никакой синхронизации вообще. Лучше всего использовать класс String, который уже неизменяемый и финальный.


public class DemoClass{
    private final Object lock = new Object();
    public void demoMethod(){
        synchronized (lock)        {
            //other thread safe code
        }
    }
}



блокировка на уровне Класса:


class MyClass {
   private static String name1 = "Оля";
   private static String name2 = "Лена";

   public static void swap() {
       synchronized (MyClass.class) {
           String s = name1;
           name1 = name2;
           name2 = s;
       }
   }

}



Некоторые важные замечания :


Пример :


public class BadSynchronized {

    public static void main(String[] args) throws Exception{
        Resource resource = new Resource(8);

        MyThread thread1 = new MyThread(resource);
        thread1.setName("firstThread");
        MyThread thread2 = new MyThread(resource);

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();


        System.out.println(resource.getI());
    }
}
      class MyThread extends Thread{
        private final Resource resource;

         MyThread(Resource res) { resource=res; }

         @Override
         public void run() {
             resource.incrementI();
         }
     }

      class Resource {
         private int i;
      /* synchronized  */  void incrementI(){
             int iLocal = this.i;
             if(Thread.currentThread().getName().equals("firstThread")){
                 Thread.yield();
             }
             iLocal++;
             this.i =iLocal;
         }
          Resource(int i) { this.i = i; }
          int getI() { return i; }
    }


Полезные ссылки: