博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2.synchronized同步锁
阅读量:7052 次
发布时间:2019-06-28

本文共 1797 字,大约阅读时间需要 5 分钟。

原文链接:

简介

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, enter0, leave1, enter1, 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为弱一致性。

转载于:https://www.cnblogs.com/xuzekun/p/7481816.html

你可能感兴趣的文章
《VMware虚拟化与计算应用案例详解》第三次印刷!
查看>>
Lync Server 2013企业版部署系列之六:AD准备
查看>>
ORA-600 [Kgeade_is_0]内部错误一例
查看>>
六个SEO关键词分析工具
查看>>
SQL Server 的一些操作
查看>>
FootPrint提取并自动化建模(简化)
查看>>
【技术贴】百度输入法老皮肤下载|百度输入法老的默认皮肤|百度皮肤下载
查看>>
discuz x2.5 模版制作 滚动图片
查看>>
使用GDB和Valgrind调试C程序
查看>>
不可思议,40个令人惊叹的iOS应用程序图标的设计灵感
查看>>
apache设置多个虚拟主机使多个域名可行有两种办法:1.多个IP解析到不同虚拟主机 2.单个IP绑定多个域名分解...
查看>>
mochiweb 源码阅读(十七)
查看>>
POJ 1946 Cow Cycling (dp推荐)
查看>>
FC/NES 音乐示例程序 生日快乐歌
查看>>
[AX]AX2012开发新特性-UnitOfWork
查看>>
WindowsPhone-GameBoy模拟器开发系列
查看>>
什么时候用Vector, 什么时候改用ArrayList?
查看>>
HDU 4334
查看>>
[Android疑难杂症]动态设置TextView的width不起作用
查看>>
PHP 逆转单链表
查看>>