Java 类级锁与对象级锁

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3718148/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 03:53:00  来源:igfitidea点击:

Java class level lock vs. object level lock

javamultithreadinglocking

提问by kgi

If a thread T1 enters a method m1 by obtaining the class level lock, does this mean another thread T2 cannot run a different method m2 by obtaining the object level lock?

如果一个线程T1通过获取类级锁进入方法m1,这是否意味着另一个线程T2不能通过获取对象级锁来运行不同的方法m2?

回答by Mark Peters

No, it doesn't mean that. The "class level lock" is just a regular lock on a different object, namely SomeClass.class. The "object level lock" locks on this.

不,不是那个意思。“类级锁”只是对不同对象的常规锁,即SomeClass.class. “对象级锁”锁定在this.

Edit:Just to make sure I'm following your understanding of the terminology, you're wondering if m1 and m2 can be run concurrently as they are defined below:

编辑:为了确保我遵循您对术语的理解,您想知道 m1 和 m2 是否可以同时运行,因为它们的定义如下:

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

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

And the answer is yes, m1 and m2 can be run concurrently. It is functionally equivalent to this:

答案是肯定的,m1 和 m2 可以同时运行。它在功能上等同于:

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

Since they are synchronizing on completely different objects, they are not mutually exclusive.

由于它们在完全不同的对象上同步,因此它们并不相互排斥。

回答by Himanshu Mohta

In java there are two types of locks:

在java中有两种类型的锁:

  1. Class Level
  2. Object Level
  1. 班级
  2. 对象级别

In case of Static methods the lock is always checked on class but in case of instance methods the lock is always checked on object.

在静态方法的情况下,锁总是在类上检查,但在实例方法的情况下,锁总是在对象上检查。

Example:

例子:

show1()is non staticand show()is static. Now, show()is called by class name (or by object) and show1()is called by object, then both methods can accessed simultaneously by two threads.

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");
    }
}

Output:

输出:

Starting in method one 10
Starting show1 two
Ending from method one 20
Ending from show1 two        

回答by Snehal Masne

Object level locking:

对象级锁定:

Object level locking is mechanism when you want to synchronize a non-static method or non-static code block such that only one thread will be able to execute the code block on given instance of the class. This should always be done to make instance level data thread safe. This can be done as below :

当您想要同步非静态方法或非静态代码块时,对象级锁定是一种机制,以便只有一个线程能够在类的给定实例上执行代码块。应该始终这样做以使实例级数据线程安全。这可以如下完成:

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 
 } 
} 


Class level locking:

类级别锁定:

Class level locking prevents multiple threads to enter in synchronized block in any of all available instances on runtime. This means if in runtime there are 100 instances of DemoClass, then only one thread will be able to execute demoMethod() in any one of instance at a time, and all other instances will be locked for other threads. This should always be done to make static data thread safe.

类级别锁定可防止多个线程在运行时进入所有可用实例中的任何一个同步块中。这意味着如果在运行时有 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 
  } 
 } 
}

回答by Subha Chandra

Example to understand Object and Class level locks in Java

了解 Java 中对象和类级别锁的示例

1) Object Level lock example

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();
    }
}

output:

输出:

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

Note that t3 will not block when threads t1 and t2 block. Because the lock is placed on this object and thread t3 has different this objectthan thread t1,t2

请注意,当线程 t1 和 t2 阻塞时,t3 不会阻塞。因为锁是放在这个对象上的,并且线程t3和线程 t1,t2有不同的这个对象

2) Class Level lock example

2) 类级锁示例

The code in object level lock, only Foo.class is added in synchronized block. All the threads are getting created using object of Foo class will get blocked.

对象级锁的代码,synchronized块中只添加了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();
    }
}

output:

输出:

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

Synchronized block is going to be executed for the same thread.

同步块将为同一个线程执行。

回答by Premraj

It's possible that both static synchronized and non static synchronized method can run simultaneously or concurrently because they lock on different object.

静态同步和非静态同步方法可能同时或并发运行,因为它们锁定在不同的对象上。

Courtesy

礼貌

回答by aayush mohanka

Class level lock is achieved by keyword "Static Synchronized,where as object level is achieved only by synchronized keyword. Object level lock is achieved to restrict same object to operate through different thread,where as class level lock is achieved to restrict any object to operate.

类级锁是通过关键字“Static Synchronized”来实现的,而对象级只能通过synchronized关键字来实现。对象级锁是为了限制同一个对象通过不同的线程进行操作,而类级锁是为了限制任何对象的操作.

回答by Manjunath Maruthi

Different ways of class level locking: 1) public class DemoClass {

类级别锁定的不同方式: 1) public class DemoClass {

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

}

}

2)

2)

public class DemoClass {

公共类演示类{

public void demoMethod(){

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

}

}

3)

3)

public class DemoClass {

公共类演示类{

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

    synchronized(lock){
        //dosomething
    } 
}

}

}

回答by rajvineet

Class level lock and instance level lock both are different. Both don't interfere each other lock status. If one instance of a class has already got locked by a thread then another thread can't get lock for that instance until unless lock is freed by first thread. Same behaviour is there for class level lock.

类级锁和实例级锁都是不同的。两者互不干扰锁定状态。如果一个类的一个实例已经被一个线程锁定,那么除非第一个线程释放锁,否则另一个线程无法获得该实例的锁。类级锁也有相同的行为。

But if a thread acquires Class level lock then another thread can acquire lock on one of its instance. Both can work parallel.`

但是如果一个线程获得了类级别的锁,那么另一个线程可以在它的一个实例上获得锁。两者都可以并行工作。`

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();
        }
    }
}

`

`

This will print : - Instance2 Class Instance 1true

这将打印: - Instance2 Class Instance 1true

All will get printed instantly without any pause.

所有内容都会立即打印,没有任何停顿。

回答by Ravindra babu

If a thread T1 enters a method m1 by obtaining the class level lock, does this mean another thread T2 cannot run a different method m2 by obtaining the object level lock?

如果一个线程T1通过获取类级锁进入方法m1,这是否意味着另一个线程T2不能通过获取对象级锁来运行不同的方法m2?

Object level lock and Class level locks are different. In above case, T2 can run method m2 by obtaining object level lock. But if m2 is static synchronized, T2 can't invoke m2 method unless T1 release class level lock on method m1.

对象级锁和类级锁是不同的。在上述情况下,T2 可以通过获取对象级锁来运行方法 m2。但是如果 m2 是static synchronized,则 T2 不能调用 m2 方法,除非 T1 释放方法 m1 上的类级锁。

Object level lock:

对象级锁

It is not possible for two invocations of synchronizedmethods on the same object to interleave. When one thread is executing a synchronizedmethod for an object, all other threads that invoke synchronizedmethods for the same object block (suspend execution) until the first thread is done with the object.

synchronized同一对象上的两次方法调用不可能交错。当一个线程正在执行synchronized对象的方法时,调用synchronized同一对象的方法的所有其他线程都会阻塞(挂起执行),直到第一个线程完成对对象的处理。

Assume that you have two synchronizedmethods m1 and m2 on Object O. If Thread T1 is in middle of execution of method m1, then Thread T2 has to wait to call method m2 on same object O unless Thread T1 release lock on method m1.

假设您synchronized在对象 O 上有两个方法 m1 和 m2。如果线程 T1 正在执行方法 m1 的中间,则线程 T2 必须等待调用同一对象 O 上的方法 m2,除非线程 T1 释放方法 m1 上的锁。

Class level lock:

类级锁

Thread acquires the intrinsic lock for the Classobject associated with the class. Thus access to class's staticfields is controlled by a lock that's distinct from the lock for any instance of the class.

线程获取Class与类关联的对象的内在锁。因此,对类static字段的访问是由一个与该类的任何实例的锁不同的锁控制的。

Assume that method m1 is static synchrnozedand method m2 is also static synchronizedand you have two different objects o1 and o2.

假设方法 m1 是static synchrnozed,方法 m2 也是,static synchronized并且您有两个不同的对象 o1 和 o2。

If Thread T1 is in middle of execution of method m1 on object o1, then Thread T2 has to wait to call method m2 on object o2 unless Thread T1 release lock on method m1.

如果线程 T1 正在执行对象 o1 上的方法 m1,则线程 T2 必须等待调用对象 o2 上的方法 m2,除非线程 T1 释放方法 m1 上的锁。

回答by Deepak Agrawal

Nope, both can execute concurrently. 1.When class level lock is applied on one method synchronized(SomeClass.class)and on other method object level lock is applied synchronized(this)then, both can execute at same time.

不,两者可以同时执行。1.当在一个方法synchronized(SomeClass.class)上应用类级锁并且在另一个方法上应用对象级锁synchronized(this)时,两者可以同时执行。

only when class level lock is applied on both methods then there is no concurrent execution.

仅当对这两种方法应用类级锁时,才不会并发执行。

Reason being: for class, jvm creates object for java.lang.Class, i.e. in short everything in java is object. So, when class level lock is applied on 2 methods, common lock is applied on class object and every object has single lock so, every thread waits, but when different instance is used to invoke the 2nd method and instance level lock is applied at that time, this object lock is applied which is different from class object lock and so concurrent execution is possible.

原因是:对于类,jvm 为 java.lang.Class 创建对象,即简而言之,java 中的一切都是对象。因此,当对 2 个方法应用类级锁时,在类对象上应用公共锁,每个对象都有单锁,因此,每个线程都在等待,但是当使用不同的实例来调用第二个方法并在那里应用实例级锁时时间,这个对象锁被应用,这与类对象锁不同,因此并发执行是可能的。