zl程序教程

您现在的位置是:首页 >  Java

当前栏目

synchronized(this)、synchronized(.class)、锁静态方法、方法区别?

2023-02-18 16:29:06 时间

一、synchronized 与 synchronized static区别?

synchronized:对像的当前实例进行加锁,防止其他线程同时访问该类实例的所有synchronized块。

synchronized static:是限制线程同时访问jvm中该类的所有实例同时访问对应的代码块,且该类的所有代码块共用一把锁。

pulbic class syncMethod(){
 
       public synchronized void syncA(){}
 
       public synchronized void syncB(){}
 
       public static synchronized void staticA(){}
 
       public static synchronized void staticB(){}
 
}

假设上面的类有四个方法,然后有两个实例a,b调用,那么哪些可以同时被访问呢?

1、a.syncA() 和 a.syncB()。

2、a.syncA() 和 b.syncB()。

3、a.staticA() 和 b.staticB()。

4、a.staticA() 和 syncMethod.staticB()。

这里我们可以根据上面两个定律判断:

1、这个肯定是可以加锁成功,两个线程不能同时访问。

2、这个肯定加锁失败,两个线程可以同时访问。

3、这个因为是静态,而且是不同的实例,根据定律也是可以加锁成功,两个线程不能同时访问。

4、这里因为一个是实例方法锁,一个是类方法锁,锁的对象不同,所以可以被同时访问。

二、synchornized(this)和synchronized(.class)

对象锁只对当前对象进行加锁,锁this和synchronized普通方法一样,只对调用的实例进行加锁,而锁.class是指对类加锁。

synchornized(this)

public class Sync823 {

    public static void main(String[] args) {
        Service823 service823 = new Service823();
        ThreadA823 threadA823 = new ThreadA823(service823);
        threadA823.setName("鸣人");
        threadA823.start();

        Service823 service82311 = new Service823();
        ThreadB823 threadB823 = new ThreadB823(service823);
        threadB823.setName("佐助");
        threadB823.start();
    }

}

class Service823{

    void thread823(){
        synchronized (this){
            for (int i = 0; i < 100; i++) {
                if(Thread.currentThread().getName().equals("鸣人")){
                    System.out.println("鸣人释放 螺旋丸");
                    continue;
                }
                System.out.println("佐助释放 千鸟");
            }
        }
    }
}

class ThreadA823 extends Thread{

    private Service823 service823;

    ThreadA823(Service823 service823){
        this.service823 = service823;
    }

    @Override
    public void run() {
        service823.thread823();
    }
}

class ThreadB823 extends Thread{

    private Service823 service823;

    ThreadB823(Service823 service823){
        this.service823 = service823;
    }

    @Override
    public void run() {
        service823.thread823();
    }
}




鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
佐助释放 千鸟
佐助释放 千鸟
佐助释放 千鸟
佐助释放 千鸟
佐助释放 千鸟

从上面代码可以看到,当锁this的时候,当是同一个实例,这时候是上锁成功,两个线程不会同时访问,和前面的synchronized修饰普通方法一样,但如果换成 不同的实例,则不会互斥。

public static void main(String[] args) {
        Service823 service823 = new Service823();
        ThreadA823 threadA823 = new ThreadA823(service823);
        threadA823.setName("鸣人");
        threadA823.start();

        Service823 service82311 = new Service823();
        ThreadB823 threadB823 = new ThreadB823(service82311);
        threadB823.setName("佐助");
        threadB823.start();
    }


佐助释放 千鸟
佐助释放 千鸟
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
佐助释放 千鸟
佐助释放 千鸟

synchronized(.class)

 synchronized (Service823.class){
            for (int i = 0; i < 100; i++) {
                if(Thread.currentThread().getName().equals("鸣人")){
                    System.out.println("鸣人释放 螺旋丸");
                    continue;
                }
                System.out.println("佐助释放 千鸟");
            }
        }


鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
鸣人释放 螺旋丸
佐助释放 千鸟
佐助释放 千鸟
佐助释放 千鸟
佐助释放 千鸟

这时候会发现,无论是创建几个实例,都会互斥成功,所以锁.class锁的是这个类,并不是实例。