Блокировка уровня класса Java и блокировка уровня объекта

Если поток T1 входит в метод m1, получив блокировку уровня класса, означает ли это, что другой поток T2 не может запустить другой метод m2, получив блокировку уровня объекта?

14
15 сент. '10 в 16:38
источник поделиться
9 ответов

Нет, это не значит. "Блокировка уровня класса" представляет собой обычную блокировку для другого объекта, а именно SomeClass.class. "Блокировка уровня объекта" блокируется на this.

Изменить:. Чтобы убедиться, что я следую вашему пониманию терминологии, вам интересно, можно ли запускать m1 и m2 одновременно, как они определены ниже:

public class SomeClass {
    public synchronized static void m1() {
       //do something
    }

    public synchronized void m2() {
       //do something
    }
}

И ответ да, m1 и m2 могут запускаться одновременно. Он функционально эквивалентен этому:

public class SomeClass {
    public static void m1() {
        synchronized (SomeClass.class) {
           //do something
        }
    }
    public void m2() {
        synchronized (this) {
           //do something
        }
    }
}

Поскольку они синхронизируются на совершенно разных объектах, они не являются взаимоисключающими.

38
15 сент. '10 в 16:38
источник

Блокировка уровня объекта:

Блокировка уровня объектов - это механизм, когда вы хотите синхронизировать нестатический метод или нестатический блок кода, чтобы только один поток мог выполнять блок кода для данного экземпляра класса. Это всегда должно быть сделано для обеспечения безопасного потока данных уровня экземпляра. Это можно сделать следующим образом:

public class DemoClass 
{ 
  public synchronized void demoMethod(){} 
} 

or 

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

or 

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

Блокировка уровня класса:

Блокировка уровня классов предотвращает включение нескольких потоков в синхронизированный блок в любом из доступных экземпляров во время выполнения. Это означает, что если во время выполнения имеется 100 экземпляров DemoClass, то только один поток сможет выполнять demoMethod() в любом экземпляре за раз, а все остальные экземпляры будут заблокированы для других потоков. Это всегда должно быть сделано для обеспечения безопасности статических данных.

public class DemoClass 
{ 
  public synchronized static void demoMethod(){} 
} 

or 

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

or 

public class DemoClass 
{ 
 private final static Object lock = new Object(); 
 public void demoMethod(){ 
 synchronized (lock) 
  { 
   //other thread safe code 
  } 
 } 
}
10
24 янв. '14 в 22:03
источник

В java есть два типа блокировок:

  • Уровень класса
  • Уровень объекта

В случае статических методов блокировка всегда проверяется на классе    но в случае методов экземпляра блокировка всегда проверяется на объекте.

Пример:

show1() не статичен, а show() является статическим. Теперь show() вызывается именем класса (или объектом) и show1() вызывается объектом, тогда оба метода могут быть доступны одновременно двумя потоками.

class Shared{
    static int x;
    static synchronized void show(String s,int a){
        x=a;
        System.out.println("Starting in method "+s+" "+x);
        try{
            Thread.sleep(2000);
        }
        catch(Exception e){ }
        System.out.println("Ending from method "+s+" "+x);
    }
    synchronized void show1(String s,int a){
        x=a;
        System.out.println("Starting show1 "+s);
        try{
            Thread.sleep(2000);
        }
        catch(Exception e){ }
        System.out.println("Ending from show1 "+s);
    }
}
class CustomThread extends Thread{
    Shared s;
    public CustomThread(Shared s,String str){
        super(str);
        this.s=s;
        start();
    }
    public void run(){
        Shared.show(Thread.currentThread().getName(),10);
    }
}
class CustomThread1 extends Thread{
    Shared s;
    public CustomThread1(Shared s,String str){
        super(str);
        this.s=s;
        start();
    }
    public void run(){
        s.show1(Thread.currentThread().getName(),20);
    }
}
public class RunSync {
    public static void main(String[] args) {
        Shared sh=new Shared();
        CustomThread t1=new CustomThread(sh,"one");
        CustomThread1 t2=new CustomThread1(sh,"two");
    }
}

Вывод:

Starting in method one 10
Starting show1 two
Ending from method one 20
Ending from show1 two        
6
18 мая '12 в 10:37
источник

Если поток T1 входит в метод m1, получив блокировку уровня класса, означает ли это, что другой поток T2 не может запустить другой метод m2, получив блокировку уровня объекта?

Блокировка уровня объекта и блокировки уровня класса различны. В приведенном выше случае T2 может запустить метод m2, получив блокировку уровня объекта. Но если m2 static synchronized, T2 не может вызвать метод m2, если T1 не блокирует уровень класса класса на методе m1.

Блокировка уровня объекта:

Невозможно чередование двух вызовов методов synchronized на одном и том же объекте. Когда один поток выполняет метод synchronized для объекта, все остальные потоки, которые вызывают методы synchronized для одного и того же объекта (приостановить выполнение) до тех пор, пока первый поток не будет выполнен с объектом.

Предположим, что у объекта есть два метода synchronized m1 и m2. Если Thread T1 находится в середине выполнения метода m1, то Thread T2 должен ждать, чтобы вызвать метод m2 на том же объекте O, если Thread T1 не заблокирует метод m1.

Блокировка уровня класса:

Thread получает встроенную блокировку для объекта Class, связанного с классом. Таким образом, доступ к классам static управляется блокировкой, отличной от блокировки для любого экземпляра класса.

Предположим, что метод m1 равен static synchrnozed, а метод m2 также static synchronized, и у вас есть два разных объекта o1 и o2.

Если Thread T1 находится в середине выполнения метода m1 на объекте o1, то Thread T2 должен ждать, чтобы вызвать метод m2 на объекте o2, если только Thread T1 не заблокирует метод m1.

2
27 мая '17 в 16:53
источник

Пример для понимания блокировок уровня Object и Class в Java

1) Пример блокировки уровня объекта

package com.test;

public class Foo implements Runnable {

    @Override
    public void run() {
        Lock();
    }
    public void Lock() {
        System.out.println(Thread.currentThread().getName());
        synchronized(this) {
            System.out.println("in block " + Thread.currentThread().getName());
            System.out.println("in block " + Thread.currentThread().getName() + " end");
        }
    }

    public static void main(String[] args) {
        Foo b1 = new Foo();
        Thread t1 = new Thread(b1);
        Thread t2 = new Thread(b1);             
        Foo b2 = new Foo();
        Thread t3 = new Thread(b2);             
        t1.setName("t1");
        t2.setName("t2");
        t3.setName("t3");             
        t1.start();
        t2.start();
        t3.start();
    }
}

выход:

    t1
    t3
    t2
    in block t3
    in block t1
    in block t3 end
    in block t1 end
    in block t2

Обратите внимание, что t3 не будет блокироваться при блокировании потоков t1 и t2. Поскольку блокировка помещается на этот объект, а поток t3 имеет другой объект, чем поток t1, t2

2) Пример блокировки на уровне классов

Код в блокировке уровня объекта добавлен только Foo.class в синхронизированном блоке. Все потоки создаются с использованием объекта класса Foo, будут заблокированы.

package com.test;    
public class Foo implements Runnable {        
    @Override
    public void run() {
        Lock();
    }

    public void Lock() {
        System.out.println(Thread.currentThread().getName());
        synchronized(Foo.class) {
            System.out.println("in block " + Thread.currentThread().getName());
            System.out.println("in block " + Thread.currentThread().getName() + " end");
        }
    }

    public static void main(String[] args) {
        Foo b1 = new Foo();
        Thread t1 = new Thread(b1);
        Thread t2 = new Thread(b1);             
        Foo b2 = new Foo();
        Thread t3 = new Thread(b2);             
        t1.setName("t1");
        t2.setName("t2");
        t3.setName("t3");             
        t1.start();
        t2.start();
        t3.start();
    }
}

выход:

t1
t3
in block t1
in block t1 end
t2
in block t3
in block t3 end
in block t2
in block t2 end

Синхронный блок будет выполнен для одного и того же потока.

2
25 июня '15 в 12:04
источник

Блокировка уровня класса достигается с помощью ключевого слова "Статическая синхронизация", где в качестве уровня объекта достигается только синхронизированное ключевое слово. Блокировка уровня объекта достигается, чтобы ограничить работу одного и того же объекта с помощью другого потока, где, поскольку блокировка уровня класса достигается, чтобы ограничить работу любого объекта.

1
18 сент. '16 в 10:20
источник

Возможно, что как статический синхронизированный, так и нестационарный синхронизированный метод могут выполняться одновременно или одновременно, потому что они блокируют другой объект.

Предоставлено

0
30 июня '15 в 10:09
источник

Различные способы блокировки уровня: 1) открытый класс DemoClass {

public static synchronized void demoMethod(){
    //dosomething
}

}

2)

публичный класс DemoClass {

public void demoMethod(){

    synchronized(DemoClass.class){
        //dosomething
    } 
}

}

3)

публичный класс DemoClass {

private final static Object lock = new Object(); 
public void demoMethod(){

    synchronized(lock){
        //dosomething
    } 
}

}

0
20 апр. '17 в 7:38
источник

Блокировка уровня класса и блокировка уровня экземпляра разные. Оба не вмешиваются друг в друга. Если один экземпляр класса уже заблокирован потоком, тогда другой поток не может получить блокировку для этого экземпляра, пока только блокировка не будет освобождена первым потоком. Такое же поведение существует для блокировки уровня класса.

Но если поток получает блокировку уровня Класса, тогда другой поток может получить блокировку на одном из своих экземпляров. Оба могут работать параллельно.

package lock;

class LockA implements Runnable {
    @Override
    public void run() {
        synchronized (LockA.class) {
            System.out.println("Class");
            try {
                Thread.sleep(60 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class TestClassVsInstanceLock {
    public static void main(String[] args) {
        final LockA a = new LockA();
        final LockA b = new LockA();
        try {
            Thread t = new Thread(a);
            Thread t1 = new Thread() {
                @Override
                public void run() {
                    synchronized (b) {
                        System.out.println("Instance 1"+ currentThread().currentThread().holdsLock(b));
                        try {
                            Thread.sleep(10 * 1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            t.start();
            t1.start();
            synchronized (a) {
                System.out.println("Instance2");
                Thread.sleep(10 * 1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

`

Это напечатает: - instance2 Класс Экземпляр 1true

Все будут распечатаны мгновенно без паузы.

0
27 мая '17 в 13:28
источник

Посмотрите другие вопросы по меткам или Задайте вопрос