美文网首页
java synchronized的初步理解

java synchronized的初步理解

作者: yizhanzjz | 来源:发表于2017-11-20 16:32 被阅读0次

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

    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对象。

    相关文章

      网友评论

          本文标题:java synchronized的初步理解

          本文链接:https://www.haomeiwen.com/subject/sdwvvxtx.html