synchronized(this)区别于synchronized(myclass-class)

(1)synchronized(myclass-class)用于静态方法中

static void myMethod() {
  synchronized(MyClass.class) {
    //code
  }
}

 

注:静态方法中只能用synchronized(MyClass.class),不能用synchronized(this)。idea中用synchronized(this)会报错。

 

等同于:

static synchronized void myMethod() {
  //code
}

 

synchronized(MyClass.class) 测试例子, 由于是静态方法, 可以被类调用,也可以被实例调用:

四个线程,两个通过实例调用,两个通过类调用

 

public class MyClass {

    public static void myMethod() {
        try {
            synchronized (MyClass.class) {
                String name = Thread.currentThread().getName();
                System.out.println(name + "线程正在开始任务。");
                for (int i = 0; i < 5; i++) {
                    Thread.sleep(1000);
                    System.out.println(name + "正在执行任务。");
                }
                System.out.println(name + "线程任务执行完毕。");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Thread thread1 = new Thread1();
        thread1.setName("thread1");
        Thread thread2 = new Thread2();
        thread2.setName("thread2");
        Thread thread3 = new Thread3();
        thread3.setName("thread3");
        Thread thread4 = new Thread4();
        thread4.setName("thread4");
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
    }
}

class Thread1 extends Thread {
    @Override
    public void run() {
        MyClass.myMethod();
    }
}

class Thread2 extends Thread {
    @Override
    public void run() {
        MyClass.myMethod();
    }
}

class Thread3 extends Thread {
    @Override
    public void run() {
        MyClass myClass = new MyClass();
        myClass.myMethod();
    }
}

class Thread4 extends Thread {
    @Override
    public void run() {
        MyClass myClass = new MyClass();
        myClass.myMethod();
    }
}

 

输出结果:

thread2线程正在开始任务。
thread2正在执行任务。
thread2正在执行任务。
thread2正在执行任务。
thread2正在执行任务。
thread2正在执行任务。
thread2线程任务执行完毕。
thread4线程正在开始任务。
thread4正在执行任务。
thread4正在执行任务。
thread4正在执行任务。
thread4正在执行任务。
thread4正在执行任务。
thread4线程任务执行完毕。
thread3线程正在开始任务。
thread3正在执行任务。
thread3正在执行任务。
thread3正在执行任务。
thread3正在执行任务。
thread3正在执行任务。
thread3线程任务执行完毕。
thread1线程正在开始任务。
thread1正在执行任务。
thread1正在执行任务。
thread1正在执行任务。
thread1正在执行任务。
thread1正在执行任务。
thread1线程任务执行完毕。

 

可以看出, 在静态方法中

synchronized(MyClass.class) {

    //code

}

只能由一个线程访问。

 

(2)synchronized(myclass-class)用于实例方法中

这个是时候只能通过创建一个实例调用。

demo测试代码:

public class MyClass {

    public void myMethod() {
        try {
            synchronized (MyClass.class) {
                String name = Thread.currentThread().getName();
                System.out.println(name + "线程正在开始任务。");
                for (int i = 0; i < 5; i++) {
                    Thread.sleep(1000);
                    System.out.println(name + "正在执行任务。");
                }
                System.out.println(name + "线程任务执行完毕。");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        final MyClass myClass = new MyClass();
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                myClass.myMethod();
            }
        });
        thread1.setName("thread1");
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                myClass.myMethod();
            }
        });
        thread2.setName("thread2");
        Thread3 thread3 = new Thread3();
        thread3.setName("thread3");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

class Thread3 extends Thread {
    @Override
    public void run() {
        MyClass myClass = new MyClass();
        myClass.myMethod();
    }
}

 

thread1线程正在开始任务。
thread1正在执行任务。
thread1正在执行任务。
thread1正在执行任务。
thread1正在执行任务。
thread1正在执行任务。
thread1线程任务执行完毕。
thread3线程正在开始任务。
thread3正在执行任务。
thread3正在执行任务。
thread3正在执行任务。
thread3正在执行任务。
thread3正在执行任务。
thread3线程任务执行完毕。
thread2线程正在开始任务。
thread2正在执行任务。
thread2正在执行任务。
thread2正在执行任务。
thread2正在执行任务。
thread2正在执行任务。
thread2线程任务执行完毕。

 

这边有三个实例,两个thread1和thread2共用一个,thread3自己开辟一个实例。发现只会有一个线程访问。其他的必须等待。情况跟(1)一样。

 

(3)synchronized(this)位于实例方法中。(静态方法不能用这个)

 

测试demo:就是将(2)中的synchronized(MyClass.class)改成synchronized(this)

public class MyClass {

    public void myMethod() {
        try {
            synchronized (this) {
                String name = Thread.currentThread().getName();
                System.out.println(name + "线程正在开始任务。");
                for (int i = 0; i < 5; i++) {
                    Thread.sleep(1000);
                    System.out.println(name + "正在执行任务。");
                }
                System.out.println(name + "线程任务执行完毕。");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        final MyClass myClass = new MyClass();
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                myClass.myMethod();
            }
        });
        thread1.setName("thread1");
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                myClass.myMethod();
            }
        });
        thread2.setName("thread2");
        Thread3 thread3 = new Thread3();
        thread3.setName("thread3");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

class Thread3 extends Thread {
    @Override
    public void run() {
        MyClass myClass = new MyClass();
        myClass.myMethod();
    }
}

 

输出1:

thread2线程正在开始任务。
thread3线程正在开始任务。
thread2正在执行任务。
thread3正在执行任务。
thread3正在执行任务。
thread2正在执行任务。
thread3正在执行任务。
thread2正在执行任务。
thread2正在执行任务。
thread3正在执行任务。
thread3正在执行任务。
thread3线程任务执行完毕。
thread2正在执行任务。
thread2线程任务执行完毕。
thread1线程正在开始任务。
thread1正在执行任务。
thread1正在执行任务。
thread1正在执行任务。
thread1正在执行任务。
thread1正在执行任务。
thread1线程任务执行完毕。

 

输出2

thread3线程正在开始任务。
thread1线程正在开始任务。
thread1正在执行任务。
thread3正在执行任务。
thread1正在执行任务。
thread3正在执行任务。
thread1正在执行任务。
thread3正在执行任务。
thread3正在执行任务。
thread1正在执行任务。
thread3正在执行任务。
thread3线程任务执行完毕。
thread1正在执行任务。
thread1线程任务执行完毕。
thread2线程正在开始任务。
thread2正在执行任务。
thread2正在执行任务。
thread2正在执行任务。
thread2正在执行任务。
thread2正在执行任务。
thread2线程任务执行完毕。

 

可以看出thread1和thread2是牵制的, 一前一后。thread3不受影响。

 

总结:

1. synchronized(myclass-class)可用于静态方法或者实例方法中,可以通过类名或者实例进行调用,但是都会只有一个线程执行,其他等待。

2. synchronized(this)只能在实例方法中进行调用,这个时候如果是同一个实例,则会互相牵制,如果是不同实例,将互不影响。

 

posted @ 2019-12-28 22:35  护花使者  Views(384)  Comments(0Edit  收藏  举报