这里我们先创建ObjLock类,并实现Runnable接口。并创建一个Demo类,具有被synchronized关键字修饰的非静态方法与静态方法。

非静态方法

public class ObjLock implements Runnable {

    Demo demo;

    public ObjLock(Demo demo){
this.demo = demo;
} public void run() {
demo.getI(Thread.currentThread().getName());
} public static void main(String[] args){
Demo demo = new Demo(1);
Thread thread = new Thread(new ObjLock(demo),"thread0");
Thread thread1 = new Thread(new ObjLock(demo),"thread1");
Thread thread2 = new Thread(new ObjLock(new Demo(2)),"thread2");
thread.start();
thread1.start();
thread2.start();
}
} class Demo{ static int i; Demo(int i){
this.i=i;
} public static synchronized void staticGetI(String s){
for (int j=0;j<10000;j++){
System.out.println(i+"---------"+s);
}
} public synchronized void getI(String s){
for (int j=0;j<10000;j++){
System.out.println(i+"---------"+s);
}
}
}

运行程序,可以看到如下结果:

1---------thread0
1---------thread0
2---------thread2
1---------thread0
2---------thread2
1---------thread0
1---------thread1
1---------thread1
2---------thread2
1---------thread1
1---------thread1
1---------thread1

可以看到Thread0和Thread2交替出现,Thread1和Thread2交替出现,但Thread0和Thread1不会交替出现。

因为对非静态方法加锁,实际上是对调用该方法的对象加锁。Thread0和Thread1用的是同一个对象,所以互斥,但是Thread2则不受影响。

静态方法

将getI方法改成static之后

public void run() {
demo.staticGetI(Thread.currentThread().getName());
}

测试发现三个线程均互斥。

当synchronized修饰一个static方法时,多线程下,获取的是类锁(即Class本身,注意:不是实例),作用范围是整个静态方法,作用的对象是这个类的所有对象。

一个对象在两个线程中分别调用一个静态同步方法和一个非静态同步方法

修改代码

public void run() {
if (Thread.currentThread().getName().equals("thread0")){
demo.staticGetI(Thread.currentThread().getName());
}else if (Thread.currentThread().getName().equals("thread1")){
demo.getI(Thread.currentThread().getName());
}
}

结果:不会产生互斥。

解释:因为虽然是一个对象调用,但是两个方法的锁类型不同,调用的静态方法实际上是类对象在调用,即这两个方法产生的并不是同一个对象锁,因此不会互斥,会并发执行。

synchronized关键字修饰非静态方法与静态方法的区别的更多相关文章

  1. 【synchronized锁】通过synchronized锁 反编译查看字节码指令分析synchronized关键字修饰方法与代码块的区别

    前提: 首先要铺垫几个前置的知识: Java中的锁如sychronize锁是对象锁,Java对象头中具有标识位,当对象锁升级为重量级锁时,重量级锁的标识位会指向监视器monitor, 而每个Java对 ...

  2. 牛客网Java刷题知识点之同步方法和同步代码块的区别(用synchronized关键字修饰)

    不多说,直接上干货! 扩展博客 牛客网Java刷题知识点之多线程同步的实现方法有哪些 为何要使用同步?      java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查 ...

  3. 多线程学习-基础( 十一)synchronized关键字修饰方法的简单案例

    一.本案例设计到的知识点 (1)Object的notify(),notifyAll(),wait()等方法 (2)Thread的sleep(),interrupt(). (3)如何终止线程. (4)如 ...

  4. synchronized修饰普通方法和静态方法

    首先,要知道,synchronized关键字修饰普通方法时,获得的锁是对象锁,也就是this.而修饰静态方法时,锁是类锁,也就是类名.class. synchronized修饰普通方法 Synchro ...

  5. Java 多线程 —— synchronized关键字

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  6. Java Concurrency - synchronized 关键字

    当有多个线程竞争共享资源时,对资源的访问顺序敏感,则可能造成数据不一致.为了保证共享资源不被多个线程同时访问,则需要将竞争共享资源的代码置于临界区,临界区保证在同一时间内最多只能有一个线程执行该代码段 ...

  7. 多线程编程-- part 3 多线程同步->synchronized关键字

    多线程同时访问一个资源,可以会产生不可预料的结果,所以为这个资源加锁,访问资源的第一个线程为其加锁后,其他线程便不能在使用那个资源,直到锁被解除. 举个例子: 存款1000元,能取出800的时候我就取 ...

  8. synchronized关键字简介 多线程中篇(十一)

    前面说过,Java对象都有与之关联的一个内部锁和监视器 内部锁是一种排它锁,能够保障原子性.可见性.有序性 从Java语言层面上说,内部锁使用synchronized关键字实现 synchronize ...

  9. Java多线程(三)—— synchronized关键字详解

    一.多线程的同步 1.为什么要引入同步机制 在多线程环境中,可能会有两个甚至更多的线程试图同时访问一个有限的资源.必须对这种潜在资源冲突进行预防. 解决方法:在线程使用一个资源时为其加锁即可. 访问资 ...

随机推荐

  1. Hibernate使用Query进行查询

    错误结果如下 Exception in thread "main" org.hibernate.hql.internal.ast.QuerySyntaxException: new ...

  2. android系统的源代码获取(亲测可用)

    1.在线阅读各版本源代码: http://androidxref.com/ 2.下载到本地: http://blog.csdn.net/yin1031468524/article/details/55 ...

  3. 升级到Angular6后对老版本的RXJS代码做相应的调整

    还没有了解过RXJS6的童鞋,可以查看我的另外一篇博文,此篇博文主要是对于RXJS5升级到RXJS6的代码调整示例 RXJS5版本 在RXJS5上我们是这样写请求的 import 'rxjs/add/ ...

  4. E20180601-hm

    trade-off n. 权衡; 交易;(不是商业方面的交易,而是“利”与“弊”的权衡) vertex n. 顶点; 最高点; <数>(三角形.圆锥体等与底相对的)顶; (三角形.多边形等 ...

  5. E20180506-hm

    更新: 2019/02/19 原来忘记分类,把此博文归入单词类 criterion n. 规范; (批评.判断等的) 标准,准则; criteria  n. (批评.判断等的) 标准,准则( crit ...

  6. C++中拷贝构造函数

    C++中拷贝构造函数 1.什么是拷贝构造函数: 拷贝构造函数嘛,当然就是拷贝和构造了.(其实很多名字,只要静下心来想一想,就真的是顾名思义呀)拷贝又称复制,因此拷贝构造函数又称复制构造函数.百度百科上 ...

  7. 剑指OFFER之二叉树的镜像(九度OJ1521)

    题目描述: 输入一个二叉树,输出其镜像. 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入的第一行为一个整数n(0<=n<=1000,n代表将要输入的二叉树节点的 ...

  8. 基础篇-psql帮助命令

    \? psql命令帮助 \h sql语句帮助 \?常用命令 1.默认  \d 后面不跟参数,则显示当前数据库所有的表 2. \d  表名  ,则显示这个表的定义 3.\d 索引名  ,显示索引的信息 ...

  9. 新建Podfile命令

    接下来,你需要建立一个主工程.建立成功以后,再次启动终端, 利用cd命令进入到工程文件夹内,此时需要创建一个特殊的文本文件,命令如下: 命令: touch Podfile 创建 命令: open -e ...

  10. Testing Complex Logic with JMeter Beanshell

    BeanShell是最先进的JMeter内置组件之一.JMeter具有丰富的内置插件,可满足性能测试的许多需求.例如,在编写一些复杂的测试时,您可能需要一些额外的脚本.在这种情况下,值得使用Beans ...