目标:
理解synchronized含义、明确synchronized关键字修饰普通方法、静态方法、和代码块时锁对象的差异
有如下一个类A
class A {
public synchronized void a() {
}
public synchronized void b() {
}
}
然后创建两个对象
A a1 = new A();
A a2 = new A();
然后在两个线程中并发访问如下代码:
Thread1 Thread2
a1.a(); a2.a();
请问二者能否构成线程同步?
如果A的定义是下面这种呢?
class A {
public static synchronized void a() {
}
public static synchronized void b() {
}
}
答案:
第一种不会同步,锁的是A的实例对象(this),a1,a2是两个不同的实例,不同线程的不同对象访问不会同步;第二种可以同步,修饰静态方法,锁的是类对象(this.class),a1和a2的同步锁一样,所以可以同步。
分析:
Synchronized是java中的关键字,是一种同步锁,用来实现多线程的同步机制,保证同一时间只有一个线程可以操作对应资源。可以修饰方法、代码块
Synchronized的机制:
Synchronized在实现同步的时候会声明一把锁,表明必须持有这把锁的线程才能访问执行,在一个线程需要执行这块代码时,会先尝试持有这把指定的锁,如果这个锁已经被别的线程持有,那么该线程就会开始等待,知道这把锁被释放后才会继续执行,并且在执行时会一直持有这把锁,以防止其他线程进入这把锁控制的代码,直到该线程执行完才会释放锁
Synchronized修饰对象有三种:
- 修饰普通方法 此时加锁的方法只允许一个线程访问,但是这种情况下锁的是该方法的实例对象(即题中Anew出来的对象),如果多个线程不同的对象访问该方法,则无法保证同步。
- 修饰静态方法 静态方法是类方法,所以此时锁的是包含这个方法的类(即A.class),也就是类对象,这种情况下,多个线程不同对象访问该静态方法,也是可以保证同步的
- 修饰代码块 修饰普通代码块同步效果跟修饰普通方法一样,修饰静态代码块同步效果和修饰静态方法类似
参考星球伙伴回答