• 2.synchronized同步锁


    原文链接:http://blog.csdn.net/zteny/article/details/54863391

    简介

    synchronized是Java语言的一个关键字,用来修饰一个方法或者代码块,使得目标达到线程同步的目的。

    当我们希望某个方法或者代码块,同一时间只能有一个线程能够执行,即是同一时间只有一个线程能够进入该方法或者代码块,其它线程将会被阻塞直接原线程执行结束,此时我们使用该关键字。

    用法

    由上面的简介可以可得synchronized的两种用法,如下:

    public synchronized void bar() {
        ...
    }
    
    public void foo() {
        synchronized(this) {
            ...
        }
    }

    1. 修饰方法

    当用synchronized修饰方法时,此时其功能相当于

    public void foo() {
        synchronized(this) {
            ...
        }
    }

    为此,我还特意看来了一下java生成class文件,发现对这两份代码生成字节码并不一样。那们为什么会这两种方式,我个人认为原因有二,当synchronized(this)的范围从方法的第一行到最后一行时,直接用synchronized修饰方法就是一种偷懒方式;其次,synchronized(this)可以有控制更小的粒度,既是只要圈住需要同步的代码可以减少的锁持有时长,提高TPS。

    如果您有更准确解释,希望您能在文后评论,谢谢

    2. 修饰代块码

    通过修饰代块码方式来实现同步的目标时,相比修饰方法有两个优势。 
    1. 只需要圈住(保护)应该圈住的代码块。被圈住的部分才会同步,其它使临界区的访问尽可能的短,从获得更好的性能。 
    2. 通引用传入的变量作为同步的标量,它允许同一时刻有多个线程同时进入同步块,当它的变量值不同时。反过来,同一时刻且同一个变量值,只允许一个线程进入同步块

    private Object v = new Object;
    public void foo() {
        synchronized(v) {
            System.out.println(Thread.currentThread().getId() + ", enter");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) { }
            System.out.println(Thread.currentThread().getId() + ", leave");
        }
    }
    
    public void bar() {
        new Thread(() -> {
            foo();
        }).start();
        new Thread(() -> {
            foo();
        }).start()
    }
    它结果应该是(发生阻塞)
    0, enter
    0, leave
    1, enter
    1, leave

    接下来我们稍微变一下,会出现一个不同的结果

    public void bar() {
        new Thread(() -> {
            v = "123";
            foo();
        }).start();
        new Thread(() -> {
            v = "321";
            foo();
        }).start()
    }
    它结果是不发生阻塞的
    

    思考

    1. 当传入的是v = 1会怎么这样呢?
    2. 当引用的是一个静态不可变变量(即static final Object v = new Object())?

      提示1,Integer a = 1; Integer b = 1;此时,a == b为true。当Integer在-128~127是全局都是同一个引用变量。 
      提示2,ClassLoader。

    FAQ

    如下这些细节找不到引入理由但又感得这些内容非常有价值,便用FAQ的方式强行带入。

      1. 能否在synchronized修饰的方法或代码块中发生线程上下文切换? 
        ——能。
      2. 简述synchronized具有可重入性。 
        ——在synchronized的方法或代码块内可以调用另一个带有synchronized的方法或代码块,而不发生死锁。
      3. 所有变量v写操作都发生synchronized代码块里,此时如果读操作不在synchronized代码块里,会怎么样呢? 
        ——此时变量v为弱一致性。
  • 相关阅读:
    美赛 LaTeX 急救指南
    切比雪夫定理的证明
    【持续更新】一个简洁、易用的美赛 LaTeX 模板: easymcm
    一个形式较精细的 Strling 公式的证明
    数学分析的主线,高等数学的一切:连续函数与“有理”分析
    一个自己稍作修改了的美赛论文 LaTeX 模板
    有关几个特殊命题的证明
    实数系与实数定理(下)
    实数系与实数定理(上)
    Office365完整离线安装包下载及自定义安装教程
  • 原文地址:https://www.cnblogs.com/xuzekun/p/7481816.html
Copyright © 2020-2023  润新知