Heim > Fragen und Antworten > Hauptteil
一个类的对象锁只有一个,如果有几个非静态函数都是synchronized,在某一时刻只有一个线程能调用其中一个函数
假如一个类有几个静态函数是synchronized,在某一时刻只有一个线程能调用其中一个静态函数吗?也就是类锁也只有一个吗?
巴扎黑2017-04-18 10:51:00
前面一种锁的是实例对象,锁定了当前的那个对象,如果有多个实例对象,这些synchronized
方法之间不是同步的。第二种锁的是类对象,类对象就一个,所以是同步的。
PHP中文网2017-04-18 10:51:00
public class Foo {
synchronized void test1() {
//to implements
}
void test2() {
synchronized(this) {
//to implements
}
}
synchronized static void test3() {
//to implements
}
static void test4() {
synchronized(Foo.class) {
//to implements
}
}
}
如上代码,test1方法相当于test2,当this是同一个对象时,会发生阻塞。当然,不同对象没有关系,因为this不一样。称为对象级锁。
test3相当于test4,这里是用class对象作为锁,因为一般情况下一个类的类实例只有一个,那么每次进入这个方法都会锁。称为类级锁。
大家讲道理2017-04-18 10:51:00
非静态同步方法(A)用的锁就是当前实例对象本身,一个实例的A获取锁之后,该实例的其他A必须等待锁的释放,多个实例用的都是不同的锁;
静态同步方法(B)用的锁是类对象本身,一旦一个B获取锁之后其他的B都必须等待释放锁,不管是一个实例还是多个实例;
另外 A和B之间用不同的锁,所以不会有竞争关系;
伊谢尔伦2017-04-18 10:51:00
你说的是“互斥锁”的概念,针对synchronized修饰方法有两种情况:
【非静态方法】
当一个方法被synchronized修饰后,锁对象为当前方法所属对象,即方法中的this。
【静态方法】
当一个静态方法被synchronized修饰后,该静态方法上锁的对象为当前类对象(Class类的实例)。每个类都有唯一的一个类对象。获取类对象的方式:类名.class。
而对于互斥的场景,需要理解两点说明:
1、静态方法与非静态方法同时声明了synchronized,他们之间是非互斥关系的。原因在于,静态方法锁的是类对象而非静态方法锁的是当前方法所属对象。
2、当Synchronized修饰的是两段不同的代码,但是锁对象相同时,两个线程分别调用者两段代码时就是互斥的
所以你说的“一时刻只有一个线程能调用其中一个函数”(即互斥),判断条件就是锁对象是否相同,与方法类型无关。
伊谢尔伦2017-04-18 10:51:00
对象方法的synchronized修饰,锁为对象自身,也就是this;
静态方法的synchronized修饰,锁为Class对象自身,也就是由类加载器创建的类对象;