关于synchronized不可描述的事情

1.synchronized的实现方式和影响效果

  • 静态方法锁

    使用这种锁,不同实例会共用同一个锁,即不同实例之间调用该方法还是需要竞争锁。好比一家人去割草,公家的镰刀只有一把,那么只能一个人用完下一个才能去拿来用。
	public  static synchronized void demo1() {
        System.out.println("静态方法锁 : demo1");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
  • 实例方法锁

    使用这种锁,不同的实例之间是不会出现锁冲突的,只用调用同一个实例的方法才会去竞争锁。好比一家人去开会,每个人都有一张嘴,每个人各说各的,互不影响,但是同一个人不能同时说两句话。
	public synchronized void demo3() {
        System.out.println("实例方法锁 : demo3");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
  • 代码块锁

    使用这样的锁,根据锁的对象,可以实现上述的实例方法锁和静态方法锁,并且比之更加灵活性和效率。因为在锁外的代码是可以定制的,且不需要竞争锁。好比一个人拿了镰刀割草,但是他说这句话之前是否先跳个舞还是三百六十度转圈再割草,这个别人管不着。

    //1. 等同于 静态方法锁
    private static Object lock = new Object();//因为这个是共享变量,所以锁住的代码也是全局锁住的
    public void demo2()  {
        synchronized (lock){//或者lock 换成 this.getClass()
            System.out.println("全局代码块锁 : demo2");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    //2.等同上面的实例方法锁 且灵活性更高
    public void demo4()  {
        synchronized (this){
            System.out.println("实例代码块锁 : demo4");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
        }
    }
    
    // 3.	改良后的动态范围锁
     //指定锁 根据构造方法将锁传入,从而控制是实例锁还是静态锁
    private Object lock2;
    public SynchronizedDemo(Object lock2) {
        this.lock2 = lock2;
    }
    public void demo5()  {
        if (null == lock2) lock2 = this.getClass();
        synchronized (lock2){
            System.out.println("范围可控锁 : demo5  : " + lock2.toString());
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    
  • main方法,看测试效果

public static void main(String[] args) throws InterruptedException {

        //静态方法锁
        new Thread(()->SynchronizedDemo.demo1()).start();
        new Thread(()->SynchronizedDemo.demo1()).start();



        SynchronizedDemo s1 = new SynchronizedDemo(new Object());
        SynchronizedDemo s2 = new SynchronizedDemo(new Object());

        new Thread(()->s1.demo2()).start();
        new Thread(()->s2.demo2()).start();


        new Thread(()->s1.demo3()).start();
        new Thread(()->s2.demo3()).start();

        new Thread(()->s1.demo4()).start();
        new Thread(()->s2.demo4()).start();

        new Thread(()->s1.demo5()).start();
        new Thread(()->s2.demo5()).start();

        Object test = new Object();
        SynchronizedDemo s3 = new SynchronizedDemo(test);
        SynchronizedDemo s4 = new SynchronizedDemo(test);
        System.out.println("test:" + test.toString());
        new Thread(()->s3.demo5()).start();
        new Thread(()->s4.demo5()).start();

        TimeUnit.SECONDS.sleep(100);


    }
  • 输出结果

静态方法锁 : demo1
全局代码块锁 : demo2
实例方法锁 : demo3
实例方法锁 : demo3
范围可控锁 : demo5 : java.lang.Object@33022318
test:java.lang.Object@5fd0d5ae
范围可控锁 : demo5 : java.lang.Object@263e1443
范围可控锁 : demo5 : java.lang.Object@5fd0d5ae
//下面部分在短暂休眠释放锁才会出来==
静态方法锁 : demo1
全局代码块锁 : demo2
实例代码块锁 : demo4
实例代码块锁 : demo4
范围可控锁 : demo5 : java.lang.Object@5fd0d5ae

synchronized锁的底层实现

任何非空对象都可以作为锁,而且根据对象的存放位置,从而影响到锁的范围,静态锁还是实例锁。锁的原理实际上利用对象头的储存空间去实现的,在对象头上标记锁的类型,记录当前获取锁的线程等属性去判断。

膨胀方向:

偏向锁 -> 轻量级锁 -> 重量级锁
  • 偏向锁:当两个线程中,基本都是一个线程(比如A)去竞争锁,那么记录下A线程,然后A线程去竞争锁时直接给予权限。(实际应用中很少有这种情况,甚至我们会去jvm设置禁用偏向锁)。这个就好比你和别人家的孩子玩耍的时候,打碎东西,挨揍的总是你一样。

-XX:-UseBiasedLocking //关闭偏向锁(默认打开)

  • 轻量级锁:最主要的锁方式,当线程竞争锁失败之后,会通过自旋的方式,再去竞争锁,如果获取成功,就继续执行,失败则自旋,直到自旋次数达到指定阈值(1.6后好像会自适应出阈值,以前默认是20次),则膨胀为重量级锁。好比我问问有没有人能给我5块钱,没有啊,那我过会再问。

JDK1.6 -XX:+UseSpinning;//开启
-XX:PreBlockSpin=10;// 为自旋次数;
JDK1.7后,去掉此自旋次数参数,由jvm控制;

  • 重量级锁:这是一个阻塞锁,如果线程竞争锁失败,就会被放入Blocking-queue的阻塞队列,等待锁被释放,根据notify或notifyall去重新唤醒进入竞争队列,然后去竞争锁。性能较低。好比我问了几次,都没人有钱,我觉得搬个椅子坐着等谁有钱。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值