您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > JAVA

java多线程,静态方法加锁后,调用该方法会影响其它方法吗?

时间:2019-12-13 10:42:19  来源:  作者:

java多线程,静态方法加锁后,调用该方法会影响其它方法吗?

从一个问题说起

一直想要把一些学习历程和感悟记录下来,却没有静下心来好好思考一下,今天,就从同学问到的一个问题开始,对同一个类的静态方法加锁后,调用该方法,其他方法的调用会受到影响吗?

对象锁与类锁

JAVA中每一个对象都持有一把锁–monitor,monitor在操作系统中被称为管程,也可翻译为监视器,java中的monitor其实是对操作系统中monitor的一种实现(类似于接口与实现)。

对象锁和类锁本质其实是一样的,只不过对象锁指的是实例对象(所持有的monitor),而类锁指的是类的Class对象。

synchronized

java中提供synchronized关键字与Object等来实现monitor机制的粒度控制。

synchronized修饰静态方法,此刻的锁指的是实例对象;

public synchronized static void syncStaticMethod(){

System.out.println("我是静态方法,我被synchronized修饰。");

}

synchronized修饰非静态方法,此刻的锁指的是类的Class对象;

public synchronized void syncMethod(){

System.out.println("我是非静态方法,我被synchronized修饰。");

}

synchronized修饰代码块,此刻的锁指的是你所赋予synchronized的对象,与方法是否静态无关;

public static void syncStaticBlockMethod() {

synchronized (Object.class) {

System.out.println("我是静态方法,我被synchronized代码块修饰,此时的锁对象是Object的Class对象。");

}

}

public void syncBlockMethod(){

synchronized (Object.class){

System.out.println("我是非静态方法,我被synchronized代码块修饰,此时的锁对象是Object的Class对象。");

}

}

分析

那么,对一个类的静态方法加锁,意味着什么?

其实,从上面我们已经可以得到答案了:当这个类的静态方法被调用时,它会去获取类锁,准确的说是该类的Class对象的monitor,那么,其他方法会受到影响吗?在这里,不妨做一个假设,那就是只要其他方法会竞争类的Class对象锁,那么它便会陷入阻塞状态(BLOCKED),直到获取Class对象锁,否则,便没有影响。

当然,最初,我们还是应当使用代码来证明(复制粘贴即可运行),如下:

/**

* @program: thinking-in-all

* @description:

* @author: Lucifinil

* @create: 2019-12-11

**/

public class SyncStaticYesAndNo implements Runnable {

public synchronized static void syncStaticYes1() {

try {

System.out.println(Thread.currentThread().getName() + " : 加锁的静态方法运行开始n");

Thread.sleep(3000);

System.out.println(Thread.currentThread().getName() + " : 加锁的静态方法运行结束");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public synchronized static void syncStaticYes2() {

try {

System.out.println(Thread.currentThread().getName() + " : 加锁的静态方法运行开始n");

Thread.sleep(3000);

System.out.println(Thread.currentThread().getName() + " : 加锁的静态方法运行结束");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public static void syncStaticNo() {

try {

System.out.println(Thread.currentThread().getName() + " : 不加锁的静态方法运行开始n");

Thread.sleep(3000);

System.out.println(Thread.currentThread().getName() + " : 不加锁的静态方法运行结束");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public synchronized void syncYes() {

try {

System.out.println(Thread.currentThread().getName() + " : 加锁的非静态方法运行开始n");

Thread.sleep(3000);

System.out.println(Thread.currentThread().getName() + " : 加锁的非静态方法运行结束");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public void syncNo() {

try {

System.out.println(Thread.currentThread().getName() + " : 不加锁的非静态方法运行开始n");

Thread.sleep(3000);

System.out.println(Thread.currentThread().getName() + " : 不加锁的非静态方法运行结束");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public static void syncStaticClassYes() {

synchronized (SyncStaticYesAndNo.class) {

try {

System.out.println(Thread.currentThread().getName() + " : 加Class对象锁的静态方法运行开始n");

Thread.sleep(3000);

System.out.println(Thread.currentThread().getName() + " : 加Class对象锁的静态方法运行结束");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

public void syncClassYes() {

synchronized (SyncStaticYesAndNo.class) {

try {

System.out.println(Thread.currentThread().getName() + " : 加Class对象锁的非静态方法运行开始n");

Thread.sleep(3000);

System.out.println(Thread.currentThread().getName() + " : 加Class对象锁的非静态方法运行结束");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

@Override

public void run() {

if (Thread.currentThread().getName().equals("Thread-0")) {

syncStaticYes1();

} else if (Thread.currentThread().getName().equals("Thread-1")) {

syncStaticYes2();

} else if (Thread.currentThread().getName().equals("Thread-2")) {

syncStaticNo();

} else if (Thread.currentThread().getName().equals("Thread-3")) {

syncYes();

} else if (Thread.currentThread().getName().equals("Thread-4")) {

syncNo();

} else if (Thread.currentThread().getName().equals("Thread-5")) {

syncStaticClassYes();

} else if (Thread.currentThread().getName().equals("Thread-6")) {

syncClassYes();

}

}

public static void main(String[] args) {

SyncStaticYesAndNo obj = new SyncStaticYesAndNo();

Thread t1 = new Thread(obj);

Thread t2 = new Thread(obj);

Thread t3 = new Thread(obj);

Thread t4 = new Thread(obj);

Thread t5 = new Thread(obj);

Thread t6= new Thread(obj);

Thread t7 = new Thread(obj);

t1.start();

t2.start();

t3.start();

t4.start();

t5.start();

t6.start();

t7.start();

}

}

这里,我们使用了七个线程来模拟多个情况,然后几乎同时调用七个方法,由之前的分析,我们可以推测,只有竞争统一把锁,才会产生阻塞情况,所以结果如下:

Thread-1 : 加锁的静态方法运行开始

Thread-3 : 加锁的非静态方法运行开始

Thread-2 : 不加锁的静态方法运行开始

Thread-4 : 不加锁的非静态方法运行开始

Thread-3 : 加锁的非静态方法运行结束

Thread-1 : 加锁的静态方法运行结束

Thread-2 : 不加锁的静态方法运行结束

Thread-6 : 加Class对象锁的非静态方法运行开始

Thread-4 : 不加锁的非静态方法运行结束

Thread-6 : 加Class对象锁的非静态方法运行结束

Thread-5 : 加Class对象锁的静态方法运行开始

Thread-5 : 加Class对象锁的静态方法运行结束

Thread-0 : 加锁的静态方法运行开始

Thread-0 : 加锁的静态方法运行结束

结论

我们可以看到,不加锁的没有受到任何影响,而加了锁的非静态方法也没有受到任何影响,因为它所竞争的锁并非是Class对象锁,而是实例对象锁,受到影响的有synchronized修饰的静态方法,还有便是加了Class对象锁的方法,本质上便是它们都在竞争当前类的Class对象锁。

 
 
 
 


Tags:java多线程   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
AQS是什么#Java# concurrent包中有很多阻塞类如:ReentrantLock、ReentrantReadWriteLock、CountDownLatch、Semaphore、Synchronous、FutureTask等,他们的底层都是根据aqs构建...【详细内容】
2020-07-28  Tags: java多线程  点击:(47)  评论:(0)  加入收藏
java.util.concurrent.Exchanger类代表了两个线程在一个集合点可以交互数据。下面描述了一下机制: 两个线程通过Exchanger 正在交换对象数据交换对象数据是通过 exchange()方...【详细内容】
2020-07-28  Tags: java多线程  点击:(43)  评论:(0)  加入收藏
java.util.concurrent.ConcurrentMap代表着可以并发访问(存和取元素)的 Map .ConcurrentMap在继承了java.util.Map父接口的基础上额外增加了一些原子方法。ConcurrentMap实现...【详细内容】
2020-07-22  Tags: java多线程  点击:(61)  评论:(0)  加入收藏
Java 的BlockingQueue接口, java.util.concurrent.BlockingQueue, 代表着一个队列可以安全的插入和取元素.换句话说,多线程通过BlockingQueue安全的插入或者取元素,不会有任何...【详细内容】
2020-07-10  Tags: java多线程  点击:(78)  评论:(0)  加入收藏
从一个问题说起一直想要把一些学习历程和感悟记录下来,却没有静下心来好好思考一下,今天,就从同学问到的一个问题开始,对同一个类的静态方法加锁后,调用该方法,其他方法的调用会...【详细内容】
2019-12-13  Tags: java多线程  点击:(78)  评论:(0)  加入收藏
Java语言的线程,从规范的角度来说是不强制要求任何具体的实现方式的。采用1:1、N:1、M:N模型都可以。具体到我们平时常用的JVM实现,Oracle/Sun的HotSpot VM,它是用1:1模型来实...【详细内容】
2019-09-20  Tags: java多线程  点击:(128)  评论:(0)  加入收藏
更多内容,欢迎关注微信公众号:全菜工程师小辉~Lock接口的实现类ReentrantLock是实现了Lock接口的类,属于独享锁,独享锁在同一时刻仅有一个线程可以进行访问。Lock接口很简单,实现...【详细内容】
2019-08-29  Tags: java多线程  点击:(165)  评论:(0)  加入收藏
并发环境下进行编程时,需要使用锁机制来同步多线程间的操作,保证共享资源的互斥访问。加锁会带来性能上的损坏,似乎是众所周知的事情。然而,加锁本身不会带来多少的性能消耗,性...【详细内容】
2019-08-07  Tags: java多线程  点击:(244)  评论:(0)  加入收藏
线程同步可以说在日常开发中是用的很多, 但对于其内部如何实现的,一般人可能知道的并不多。 本篇文章将从如何实现简单的锁开始,介绍linux中的锁实现futex的优点及原理,最后分...【详细内容】
2019-07-29  Tags: java多线程  点击:(298)  评论:(0)  加入收藏
▌简易百科推荐
面向对象的特征之一封装 面向对象的特征之二继承 方法重写(override/overWrite) 方法的重载(overload)和重写(override)的区别: 面向对象特征之三:多态 Instanceof关键字...【详细内容】
2021-12-28  顶顶架构师    Tags:面向对象   点击:(2)  评论:(0)  加入收藏
一、Redis使用过程中一些小的注意点1、不要把Redis当成数据库来使用二、Arrays.asList常见失误需求:把数组转成list集合去处理。方法:Arrays.asList 或者 Java8的stream流式处...【详细内容】
2021-12-27  CF07    Tags:Java   点击:(3)  评论:(0)  加入收藏
文章目录 如何理解面向对象编程? JDK 和 JRE 有什么区别? 如何理解Java中封装,继承、多态特性? 如何理解Java中的字节码对象? 你是如何理解Java中的泛型的? 说说泛型应用...【详细内容】
2021-12-24  Java架构师之路    Tags:JAVA   点击:(5)  评论:(0)  加入收藏
大家好!我是老码农,一个喜欢技术、爱分享的同学,从今天开始和大家持续分享JVM调优方面的经验。JVM调优是个大话题,涉及的知识点很庞大 Java内存模型 垃圾回收机制 各种工具使用 ...【详细内容】
2021-12-23  小码匠和老码农    Tags:JVM调优   点击:(12)  评论:(0)  加入收藏
前言JDBC访问Postgresql的jsonb类型字段当然可以使用Postgresql jdbc驱动中提供的PGobject,但是这样在需要兼容多种数据库的系统开发中显得不那么通用,需要特殊处理。本文介绍...【详细内容】
2021-12-23  dingle    Tags:JDBC   点击:(13)  评论:(0)  加入收藏
Java与Lua相互调用案例比较少,因此项目使用需要做详细的性能测试,本内容只做粗略测试。目前已完成初版Lua-Java调用框架开发,后期有时间准备把框架进行抽象,并开源出来,感兴趣的...【详细内容】
2021-12-23  JAVA小白    Tags:Java   点击:(11)  评论:(0)  加入收藏
Java从版本5开始,在 java.util.concurrent.locks包内给我们提供了除了synchronized关键字以外的几个新的锁功能的实现,ReentrantLock就是其中的一个。但是这并不意味着我们可...【详细内容】
2021-12-17  小西学JAVA    Tags:JAVA并发   点击:(11)  评论:(0)  加入收藏
一、概述final是Java关键字中最常见之一,表示“最终的,不可更改”之意,在Java中也正是这个意思。有final修饰的内容,就会变得与众不同,它们会变成终极存在,其内容成为固定的存在。...【详细内容】
2021-12-15  唯一浩哥    Tags:Java基础   点击:(17)  评论:(0)  加入收藏
1、问题描述关于java中的日志管理logback,去年写过关于logback介绍的文章,这次项目中又优化了下,记录下,希望能帮到需要的朋友。2、解决方案这次其实是碰到了一个问题,一般的情况...【详细内容】
2021-12-15  软件老王    Tags:logback   点击:(19)  评论:(0)  加入收藏
本篇文章我们以AtomicInteger为例子,主要讲解下CAS(Compare And Swap)功能是如何在AtomicInteger中使用的,以及提供CAS功能的Unsafe对象。我们先从一个例子开始吧。假设现在我们...【详细内容】
2021-12-14  小西学JAVA    Tags:JAVA   点击:(22)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条