zoukankan      html  css  js  c++  java
  • synchronized关键字详解(二)

    synchronized关键字的性质

    1.可重入:同一线程的外层函数获得锁之后,内层函数可直接再次获得该锁,好处:避免死锁,提升封装性

    证明可重入粒度:1、同一个方法是可重入的

            2、可重入不要求是同一个方法

            3、可重入不要求是同一个类

    可重入原理:加锁次数计数器

        • JVM负责跟踪对象被加锁的次数;
        • 线程第一次给对象加锁的时候计数变为1,每当这个相同的线程在这个对象上加锁时,计数递增;
        • 每当任务离开时,计数会减1,计数为0时,锁被完全释放。

    2.不可中断:如果一个线程拿到一把锁,另一个线程要想获得这把锁,只能等待或者阻塞,直到别的线程释放这个锁,如果另一个线程一直不释放,那就只能一直等待下去。(相比之下,Lock类拥有中断的能力:1.lock如果等的时间太长,有权利中断当前获得锁的这个线程;2.lock等待时间太长不想等,可以自动退出)

    同一个方法是可重入的:

    递归调用method方法打印出a=1;就说明进入该方法两次

    /**
     * 
     * 验证synchronized的可重入性质1:
     * 同一个方法是可重入的
     * @author Administrator
     *
     */
    public class SynchronizeTest04 implements Runnable{
        static SynchronizeTest04 instance1 = new SynchronizeTest04();
        int a = 0;
        @Override
        public void run() {
            //调用加synchronized关键字的普通方法
            method();
        }
        public synchronized void method() {
            System.out.println("a="+a);
            if(a==0) {
                a++;
                method();
            }    
        }
        public static void main(String[] args) {
            Thread t1 = new Thread(instance1,"线程一");
            t1.start();
            while(t1.isAlive()) {
                
            }
            System.out.println("执行结束");
        }
    }
     

    可重入不要求是同一个方法:

    run方法中调用被synchronized修饰的method1方法,在method1中调用被synchronized修饰的method2方法

    /**
     * 
     * 验证synchronized的可重入性质2:
     * 可重入不要求是同一个方法
     * @author Administrator
     *
     */
    public class SynchronizeTest04 implements Runnable{
        static SynchronizeTest04 instance1 = new SynchronizeTest04();
        int a = 0;
        @Override
        public void run() {
            //调用加synchronized关键字的普通方法
            method1();
        }
        public synchronized void method1() {
            System.out.println("我是方法一");
            method2();
        }
        public synchronized void method2() {
            System.out.println("我是方法二");
        }
        public static void main(String[] args) {
            Thread t1 = new Thread(instance1,"线程一");
            t1.start();
            while(t1.isAlive()) {
                
            }
            System.out.println("执行结束");
        }
    }
    可重入不要求是同一个方法

     

    可重入不要求是同一个类:

    由于main方法就是一个线程,所以这里用main方法演示,父类中创建被synchronized修饰的doSomething方法,子类中重写doSomething方法,并调用父类方法

    /**
     * 
     * 验证synchronized的可重入性质3:
     * 可重入不要求是同一个类
     * @author Administrator
     *
     */
    public class SynchronizeTest05 {
        public synchronized void doSomething() {
            System.out.println("我是父类");
        }
        public static void main(String[] args) {
            Test t = new Test();
            t.doSomething();
        }
    }
    class Test extends SynchronizeTest05{
        //重写父类的方法,并调用父类方法
        public synchronized void doSomething() {
            System.out.println("我是子类");
            super.doSomething();
        }
    }
    可重入不要求是同一个类

     

    synchronized关键字的缺点:

    1、效率低:锁的释放少,试图获得锁时不能设置超时,不能中断一个正在获得锁的线程;

    2、不够灵活:加锁和释放的时机单一,每个锁仅有单一的条件

    3、无法知道是否成功获取到锁

    在使用synchronized关键字时注意:锁对象不能为空、锁的作用域不宜过大、避免死锁。

  • 相关阅读:
    js 变量命名规范
    JS
    python 处理中文十六进制的encode %E9%99%88%E8%80%81%E5%B8%88/%E5%9B%BE%E7%89%87
    Pycharm 项目上传至Gitee/Github详细步骤
    Python 类型建议符, Python 定义函数的时候有冒号:
    Python 解析 JSON
    Python 解析 JSON
    Mac 安装 WordPress
    java常用书籍下载
    Docker环境搭建Redis4.0 Cluster
  • 原文地址:https://www.cnblogs.com/YpfBolg/p/10805794.html
Copyright © 2011-2022 走看看