使用synchronized修饰静态方法和非静态方法有什么区别

前言并发

最近被问到了这个问题,第一次回答的也是很很差,在此参考网上答案进行整理记录。供你们学习参考。学习

Synchronized修饰非静态方法spa

Synchronized修饰非静态方法,其实是对调用该方法的对象加锁,俗称“对象锁”。线程

Java中每一个对象都有一个锁,而且是惟一的。假设分配的一个对象空间,里面有多个方法,至关于空间里面有多个小房间,若是咱们把全部的小房间都加锁,由于这个对象只有一把钥匙,所以同一时间只能有一我的打开一个小房间,而后用完了还回去,再由JVM 去分配下一个得到钥匙的人。code

状况1:同一个对象在两个线程中分别访问该对象的两个同步方法对象

结果:会产生互斥。blog

解释:由于锁针对的是对象,当对象调用一个synchronized方法时,其余同步方法须要等待其执行结束并释放锁后才能执行。正如上面所解释的,至关于一个对象只有一把钥匙了,里面的两个同步方法是两个房间,所以,同一时间只能用一个钥匙访问一个方法。同步

状况2:不一样对象在两个线程中调用同一个同步方法class

结果:不会产生互斥。方法

解释:由于是两个对象,就至关于两个大房子,彼此之间互不干扰,具备两把钥匙。锁针对的是对象,并非方法,因此能够并发执行,不会互斥。形象的来讲就是由于咱们每一个线程在调用方法的时候都是new 一个对象,那么就会出现两个空间,两把钥匙。

Synchronized修饰静态方法

Synchronized修饰静态方法,其实是对该类对象加锁,俗称“类锁”。

状况1:用类直接在两个线程中调用两个不一样的同步方法

结果:会产生互斥。

解释:由于对静态对象加锁实际上对类(.class)加锁,类对象只有一个,能够理解为任什么时候候都只有一个空间,里面有N个房间,一把锁,所以房间(同步方法)之间必定是互斥的。

注:上述状况和用单例模式声明一个对象来调用非静态方法的状况是同样的,由于永远就只有这一个对象。因此访问同步方法之间必定是互斥的。

状况2:用一个类的静态对象在两个线程中调用静态方法或非静态方法

结果:会产生互斥。

解释:由于是一个对象调用,同上。都调用静态方法的时候,至关因而同一个类锁,用的都是同一个类对象。

都调用非静态方法的时候,至关因而同一个对象锁。

状况3:一个对象在两个线程中分别调用一个静态同步方法和一个非静态同步方法

结果:不会产生互斥。

解释:由于虽然是一个对象调用,可是两个方法的锁类型不一样,调用的静态方法其实是类对象在调用,即这两个方法产生的并非同一个对象锁,所以不会互斥,会并发执行。

例子

 

pulbic class Something(){

    public synchronized void isSyncA(){}
    
    public synchronized void isSyncB(){}
    
    public static synchronized void cSyncA(){}
    
    public static synchronized void cSyncB(){}

}

那么,加入有Something类的两个实例a与b,那么下列哪组方法能够被1个以上线程同时访问呢?

a. x.isSyncA()与 x.isSyncB()

b. x.isSyncA()与 y.isSyncA()

c. x.cSyncA()与 y.cSyncB()

d. x.isSyncA()与 Something.cSyncA()

这里,很清楚的能够判断:

a,都是对同一个实例的synchronized域访问,所以不能被同时访问

b,是针对不一样实例的,所以能够同时被访问

c,由于是static synchronized,因此不一样实例之间不会被限制

d,书上的答案是能够被同时访问的,答案理由是synchronzied的是实例方法与synchronzied的类方法因为锁定(lock)不一样的缘由。

相关文章
相关标签/搜索