Synchronized

Java编程思想:每个对象都包含了一把锁(也叫作“监视器”),它自动成为对象的一部分,调用任何synchronized方法时,对象就会被锁定,不可再调用那个对象的其他任何synchronized 方法,除非第一个方法完成了自己的工作,并解除锁定。

特点:Jvm层面,非公平,悲观,独占,可重入,重量级。

作用:修饰方法和代码块。

修饰方法和代码块

synchronized修饰静态方法,我们可以称其为“类锁”,即只要有一个线程实例对象获取该锁,其他线程实例对象都需要等待。修饰非静态方法,我们称之为对象锁,即不同的线程实例对象是可以调用同一类下的同步方法。

/**
* @PackageName com.a.squirrel.synchronize
* @Author: squirrel
* @Date: 2018/6/25 10:04
* @Description: synchronized解析辅助类
*/
public class SynchronizedDescription { private String tmpStr; private int tmpInt; /**
* @Author squirrel
* @Description 非静态同步方法
* @Date 2018/6/25
* @Param [synchronizedDescription]
* @return
**/
public synchronized void testSynchronizedMethod(SynchronizedDescription synchronizedDescription){
System.out.println("线程:"+synchronizedDescription.getTmpInt()+"-->:==========我是非静态同步方法=======");
System.out.println("线程:"+synchronizedDescription.getTmpInt()+"-->:调用非静态同步方法时间为:"+getNowTime());
try {
Thread.sleep(5000);// 当前线程休眠5s,休眠过程中不会释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
} /**
* @Author squirrel
* @Description 同步代码块
* @Date 2018/6/25
* @Param [synchronizedDescription]
* @return
**/
public void testSynchronizedBlockMethod(SynchronizedDescription synchronizedDescription){
synchronized (synchronizedDescription){// 锁定实例对象
System.out.println("线程:"+synchronizedDescription.getTmpInt()+"-->:==========我是同步代码块=======");
System.out.println("线程:"+synchronizedDescription.getTmpInt()+"-->:调用同步代码块时间为:"+getNowTime());
try {
Thread.sleep(2000);// 当前线程休眠2s,休眠过程中不会释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} /**
* @Author squirrel
* @Description 静态同步方法
* @Date 2018/6/25
* @Param [synchronizedDescription]
* @return
**/
public synchronized static void testSynchronizedStaticMethod(SynchronizedDescription synchronizedDescription){
System.out.println("线程:"+synchronizedDescription.getTmpInt()+"-->:==========我是静态同步方法=======");
System.out.println("线程:"+synchronizedDescription.getTmpInt()+"-->:调用静态同步方法时间为:"+getNowTime());
try {
Thread.sleep(10000);// 当前线程休眠10s,休眠过程中不会释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
} /**
* @Author squirrel
* @Description 获取当前时间
* @Date 2018/6/25
* @Param []
* @return java.lang.String
**/
private static String getNowTime(){
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
} public SynchronizedDescription(String tmpStr, int tmpInt) {
this.tmpStr = tmpStr;
this.tmpInt = tmpInt;
} public String getTmpStr() {
return tmpStr;
} public void setTmpStr(String tmpStr) {
this.tmpStr = tmpStr;
} public int getTmpInt() {
return tmpInt;
} public void setTmpInt(int tmpInt) {
this.tmpInt = tmpInt;
}
}
/**
* @PackageName com.a.squirrel.synchronize
* @Author: squirrel
* @Date: 2018/6/25 10:10
* @Description: 测试类
*/
public class TestSynchronized { public static void main(String[] args) {
// 创建阻塞队列
final BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(100);
// 创建线程池
final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2,20,60, TimeUnit.SECONDS,queue);
threadPool.allowCoreThreadTimeOut(true);
for (int i =0;i<100;i++){
threadPool.execute(new Runnable() {
@Override
public void run() {
final String tmpStr = Thread.currentThread().getName();
final String[] split = tmpStr.split("-");
int tmpInt = Integer.parseInt(split[split.length-1]);
SynchronizedDescription synchronizedDescription = new SynchronizedDescription(tmpStr,tmpInt);
// 调用同步代码块
synchronizedDescription.testSynchronizedBlockMethod(synchronizedDescription);
// 调用非静态同步方法
synchronizedDescription.testSynchronizedMethod(synchronizedDescription);
// 调用静态同步方法
synchronizedDescription.testSynchronizedStaticMethod(synchronizedDescription);
}
});
}
}
}

运行结果可以验证以上结论:



下面我们变更同步代码块的同步对象:

    /**
* @Author squirrel
* @Description 同步代码块
* @Date 2018/6/25
* @Param [synchronizedDescription]
* @return
**/
public void testSynchronizedBlockMethod(SynchronizedDescription synchronizedDescription){
synchronized (SynchronizedDescription.class){// 锁定类对象
System.out.println("线程:"+synchronizedDescription.getTmpInt()+"-->:==========我是同步代码块=======");
System.out.println("线程:"+synchronizedDescription.getTmpInt()+"-->:调用同步代码块时间为:"+getNowTime());
try {
Thread.sleep(2000);// 当前线程休眠2s,休眠过程中不会释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}



由上图我们可以得出一个结论,这里借用一张图来说明一下这个结论:

实现原理:

深入理解Java虚拟机:对象在内存中存储的布局可以分为3块区域:对象头,实例数据和对齐填充。



synchronized对象锁其指针指向的是一个monitor对象,每个对象实例都会有一个 monitor,其中monitor可以与对象一起创建销毁,也可以在线程试图获取对象锁时自动生成。在执行monitorenter指令时,首先要尝试获取对象锁,如果这个对象没有被锁定,或者当前线程已经拥有了这个对象的锁,那么就把锁计数器加1,当执行monitorexit指令时,释放锁同时锁计数器也会减1。



Java Keyword Synchronized 学习记录的更多相关文章

  1. Java Keyword Static 学习记录

    Static Java编程思想:一旦将什么东西设为static,数据或方法就不会同那个类的任何对象实例联系到一起. 特点:随着类的加载而加载,随着类的销毁而销毁. 作用:可以修饰成员变量,代码块,方法 ...

  2. java 项目相关 学习记录

    一位资深程序员大牛给予Java初学者的学习路线建议  [任何时期都可以好好看看] https://www.imooc.com/article/8993 https://www.jianshu.com/ ...

  3. 转:java高并发学习记录-死锁,活锁,饥饿

    死锁 两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去. 为什么会产生死锁: ① 因为系统资源不足. ② 进程运行推进的顺序不合适.    ③ ...

  4. JAVA 动态代理学习记录

    打算用JAVA实现一个简单的RPC框架,看完RPC参考代码之后,感觉RPC的实现主要用到了两个方面的JAVA知识:网络通信和动态代理.因此,先补补动态代理的知识.---多看看代码中写的注释 参考:Ja ...

  5. [Hanani]JAVA大数相关学习记录

    1.Basic remains 题目链接 涉及内容: |大数读入|大数模|大数进制读入时转化为十进制|大数输出时转化为其他进制输出| import java.io.*; import java.mat ...

  6. java一周学习记录(2017/12/2)

    姓名:Danny                               日期:2017/12/2 周日 周一 周二 周三 周四 周五 周六 所花时间 120 150 190 150 180 28 ...

  7. 阿里巴巴java开发手册学习记录,php版

    一.编程规约 (一)命名风格 1.目录使用小写+下划线 home,view,model,admin_view 2.类 UpperCamelCase PhpMailer方法 lowerCamelCase ...

  8. [SRH.Docker] HBase Java 第一天学习记录

    主要对HBase Table 的 简单操作, 直接上代码吧!!! http://pan.baidu.com/s/1hqzTTze       ui92

  9. Java 类引入 学习记录规整

    之前觉得声明一个类,再把另一个包内的声明数值用第一个类打印出来就可以了(加入引入包类) 结果发现是不对的 看了看demo  得出正确结果    ImportTest 被运行 引入下面的Import类 ...

随机推荐

  1. ROS常见问题(三) 报错are you sure it is properly registered and that the containing library is built?

    报错: [FATAL] [1576042404.913706482]: Failed to create the global_planner/GlobalPlanner planner, are y ...

  2. Java笔记: protected的真正含义

    关于protected关键字,即使是Java初学者也能够说出它的含义:protected修饰的成员可以被子类访问.但是这样理解并不完全准确,下面考虑它的真正含义. Java访问控制回顾 Java语言定 ...

  3. matlab和fortran混合编程

    matlab2016b+vs2010+ivf2013+f90 其实默认是f77语法,但通过配置可以改变为自由格式. 默认只能f77代码,怎样修改: https://ww2.mathworks.cn/m ...

  4. [转]Spark SQL2.X 在100TB上的Adaptive execution(自适应执行)实践

    Spark SQL是Apache Spark最广泛使用的一个组件,它提供了非常友好的接口来分布式处理结构化数据,在很多应用领域都有成功的生产实践,但是在超大规模集群和数据集上,Spark SQL仍然遇 ...

  5. 洛谷P1433 吃奶酪 题解 状态压缩DP

    题目链接:https://www.luogu.com.cn/problem/P1433 题目大意 房间里放着 \(n\) 块奶酪.一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在 \((0, ...

  6. UVA - 11806 Cheerleaders (容斥原理)

    题意:在N*M个方格中放K个点,要求第一行,第一列,最后一行,最后一列必须放,问有多少种方法. 分析: 1.集合A,B,C,D分别代表第一行,第一列,最后一行,最后一列放. 则这四行必须放=随便放C[ ...

  7. PL/SQL表结构/数据的导出

    1.表结构导出 方法一:在sql页面点击表名,进入表编辑页面,点击右下角“查看SQL”按钮,即可看到表结构 方法二:工具--导出用户对象 去掉所有者勾选项,即***.表名:用户名字在其他用户导入数据库 ...

  8. java获取键盘事件

    转 <script type="text/javascript" language=JavaScript charset="UTF-8"> docu ...

  9. 创建了以个vagrant box centos php7 nginx swoole git

    php7.2.9 centos7  nginx.1.16  swoole4.4.4 下载地址 链接:https://pan.baidu.com/s/14p7xIa0ZZigRuYvZxnMsYA 提取 ...

  10. python虚拟环境配置(上)

    前言 嘿,小伙伴们,晚上好呀,我们又见面了,今天又给带来的是什么呢,咱们今天就来说一下python的虚拟环境,可能有的小伙伴会疑惑,python的虚拟环境有什么用呢,我们来一一探讨一下 虚拟环境的作用 ...