java synchronized的初步理解

2017-11-20  本文已影响0人  yizhanzjz

本博客每一个小标题下的内容独立且完整,如只是想了解某个小标题下的内容,只需前往看该小标题即可。

1. 多线程并发访问同一个对象的同一个非静态synchronized方法

完整代码:

public class myClass {

    public static void main(String[] args) {

        final TestClass testClass = new TestClass();

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                testClass.methodA();
            }
        }, "线程1");

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                testClass.methodA();
            }
        }, "线程2");

        thread1.start();
        thread2.start();
    }
}

class TestClass {

    /**
     * 普通同步方法A
     */
    public void methodA() {
        synchronized (this) {
            for (int i = 0; i < 4; i++) {
                System.out.println(Thread.currentThread().getName() + "正在执行methodA:" + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

小标题已经准确表达了上面这块代码的意思,运行结果如下:

同一个对象同一个非静态同步方法.png

由执行结果可知,两个线程中其中一个线程执行完才会执行第二个线程。结论就是,多个线程并发访问同一个对象的同一个非静态synchronized方法时,先获取到锁的线程执行完毕后才会执行其它线程。也就是说synchronized(this)这种锁可以锁定一个非静态synchronized方法,只让获取了该锁的线程执行,其它线程在该线程未执行完毕之前不能执行

2. 多线程并发访问同一个对象的不同非静态synchronized方法

完整代码:

public class myClass {

    public static void main(String[] args) {

        final TestClass testClass = new TestClass();

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                testClass.methodA();
            }
        }, "线程1");

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                testClass.methodB();
            }
        }, "线程2");

        thread1.start();
        thread2.start();
    }
}

class TestClass {

    /**
     * 普通同步方法A
     */
    public void methodA() {
        synchronized (this) {
            for (int i = 0; i < 4; i++) {
                System.out.println(Thread.currentThread().getName() + "正在执行methodA:" + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 普通同步方法B
     */
    public void methodB() {
        synchronized (this) {
            for (int i = 0; i < 4; i++) {
                System.out.println(Thread.currentThread().getName() + "正在执行methodB:" + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

运行结果如下:

同一个对象不同非静态同步方法.png

由执行结果可知,两个线程中其中一个线程执行完才会执行第二个线程。结论是多个线程并发访问同一个对象的不同非静态synchronized方法时,先获取到锁的线程执行完毕后才会执行其它线程。也就是说,synchronized(this)这种锁锁定的范围是该对象的所有非静态synchronized方法,而不单单是获取了该锁的线程正在执行的非静态synchronized方法

3. 多线程并发访问同一个对象的不同方法,一个是非静态synchronized方法,一个是非静态非synchronized方法

完整代码:

public class myClass {

    public static void main(String[] args) {

        final TestClass testClass = new TestClass();

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                testClass.methodA();
            }
        }, "线程1");

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                testClass.methodC();
            }
        }, "线程2");

        thread1.start();
        thread2.start();
    }
}

class TestClass {

    /**
     * 普通同步方法A
     */
    public void methodA() {
        synchronized (this) {
            for (int i = 0; i < 4; i++) {
                System.out.println(Thread.currentThread().getName() + "正在执行methodA:" + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 普通方法,非同步
     */
    public void methodC() {
        for (int i = 0; i < 4; i++) {
            System.out.println(Thread.currentThread().getName() + "正在执行methodC:" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果如下:

同一个对象一个非静态同步方法一个非静态非同步方法.png

由执行结果可知,两个线程并发执行,没有先后顺序。结论是多个线程并发访问同一个对象的不同方法时,一个是非静态synchronized方法,一个是非静态非synchronized方法,这两线程并发运行。也就是说,synchronized(this)这种锁锁定的是该对象的所有非静态synchronized方法,并不会锁定该对象的非静态非synchronized方法。

4. 多线程并发访问同一个对象的不同方法,一个是非静态synchronized方法,一个是静态synchronized方法

public class myClass {

    public static void main(String[] args) {

        final TestClass testClass = new TestClass();
//        final TestClass testClassNext = new TestClass();

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                testClass.methodA();
            }
        }, "线程1");

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                testClass.methodE();
            }
        }, "线程2");

        thread1.start();
        thread2.start();
    }
}

class TestClass {

    /**
     * 普通同步方法A
     */
    public void methodA() {
        synchronized (this) {
            for (int i = 0; i < 4; i++) {
                System.out.println(Thread.currentThread().getName() + "正在执行methodA:" + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 静态同步方法E
     */
    public synchronized static void methodE() {
        for (int i = 0; i < 4; i++) {
            System.out.println(Thread.currentThread().getName() + "正在执行methodE:" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

运行结果如下:

同一个对象一个静态同步方法一个非静态同步方法.png

由执行结果可知,两个线程并发执行,没有先后顺序。结论是多个线程并发访问同一个对象的不同方法时,一个是非静态synchronized方法,另一个是静态synchronized方法,这两线程并发运行。也就是说,,synchronized(this)这种锁锁定的范围是这个对象所有的非静态synchronized方法,而静态synchronized锁锁定的是该类的所有对象的所有静态synchronized方法,两个锁锁的作用范围不一样,执行起来就不会相互锁定

5. 多线程并发访问同一个类不同对象的同一个非静态synchronized方法

public class myClass {

    public static void main(String[] args) {

        final TestClass testClass = new TestClass();
        final TestClass testClassNext = new TestClass();

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                testClass.methodA();
            }
        }, "线程1");

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                testClassNext.methodA();
            }
        }, "线程2");

        thread1.start();
        thread2.start();
    }
}

class TestClass {

    /**
     * 普通同步方法A
     */
    public void methodA() {
        synchronized (this) {
            for (int i = 0; i < 4; i++) {
                System.out.println(Thread.currentThread().getName() + "正在执行methodA:" + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

运行结果如下:

不同对象同一个非静态同步方法.png

由执行结果可知,两个线程并发执行,没有先后顺序。结论是多个线程并发访问同一个类不同对象的同一个非静态synchronized方法时,这两线程并发运行。也就是说,synchronized(this)这种锁锁定的范围是该对象的非静态synchronized方法,而不能锁定该类的另一个实例的非静态synchronized方法。

6. 多线程并发访问同一个类的不同对象的同一个静态synchronized方法

public class myClass {

    public static void main(String[] args) {

        final TestClass testClass = new TestClass();
        final TestClass testClassNext = new TestClass();

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                testClass.methodD();
            }
        }, "线程1");

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                testClassNext.methodD();
            }
        }, "线程2");

        thread1.start();
        thread2.start();
    }
}

class TestClass {

    /**
     * 静态同步方法D
     */
    public synchronized static void methodD() {
        for (int i = 0; i < 4; i++) {
            System.out.println(Thread.currentThread().getName() + "正在执行methodD:" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果如下:

不同对象同一个静态同步方法.png

由执行结果可知,两个线程中其中一个线程执行完才会执行第二个线程。结论是多线程并发访问同一个类的不同对象的同一个静态synchronized方法时,先获取到锁的线程执行完毕之后才会执行下一个线程。也就是说,静态synchronized锁锁定的范围已经不再是单个对象的静态synchronized方法了,而是所有对象的静态synchronized方法。

上述所有情况的总结

  1. 在一个类对象范围内,非静态synchronized锁不仅锁定当前获取该锁的线程正在执行的非静态synchronized方法,还会锁定该对象的其他所有非静态synchronized方法,但不会锁定该对象的非静态非synchronized方法、静态非synchronized方法和静态synchronized方法;

  2. 非静态synchronized锁作用范围是在一个对象里,并不会干涉到其他线程调用该类的另一个对象的非静态synchronized方法,而静态synchronized锁可以影响到其它对象;

  3. 静态synchronized锁会锁定该类的所有对象的所有静态synchronized方法,但不会锁定该类的所有对象的的静态非synchronized方法、非静态synchronized方法、非静态非synchronized方法;

  4. 非静态synchronized锁锁定的是该类的一个实例对象,静态synchronized锁锁定的其实是该类的Class对象。

上一篇下一篇

猜你喜欢

热点阅读