基于synchronized修饰静态和非静态方法

前言

最近被问到了这个问题,第一次回答的也是很不好,在此参考网上答案进行整理记录。供大家学习参考。

Synchronized修饰非静态方法

Synchronized修饰非静态方法,实际上是对调用该方法的对象加锁,俗称“对象锁”。

Java中每个对象都有一个锁,并且是唯一的。假设分配的一个对象空间,里面有多个方法,相当于空间里面有多个小房间,如果我们把所有的小房间都加锁,因为这个对象只有一把钥匙,因此同一时间只能有一个人打开一个小房间,然后用完了还回去,再由JVM 去分配下一个获得钥匙的人。

情况1:同一个对象在两个线程中分别访问该对象的两个同步方法

结果:会产生互斥。

解释:因为锁针对的是对象,当对象调用一个synchronized方法时,其他同步方法需要等待其执行结束并释放锁后才能执行。正如上面所解释的,相当于一个对象只有一把钥匙了,里面的两个同步方法是两个房间,因此,同一时间只能用一个钥匙访问一个方法。

情况2:不同对象在两个线程中调用同一个同步方法

结果:不会产生互斥。

解释:因为是两个对象,就相当于两个大房子,彼此之间互不干扰,具有两把钥匙。锁针对的是对象,并不是方法,所以可以并发执行,不会互斥。形象的来说就是因为我们每个线程在调用方法的时候都是new 一个对象,那么就会出现两个空间,两把钥匙。

Synchronized修饰静态方法

Synchronized修饰静态方法,实际上是对该类对象加锁,俗称“类锁”。

情况1:用类直接在两个线程中调用两个不同的同步方法

结果:会产生互斥。

解释:因为对静态对象加锁实际上对类(.class)加锁,类对象只有一个,可以理解为任何时候都只有一个空间,里面有N个房间,一把锁,因此房间(同步方法)之间一定是互斥的。

注:上述情况和用单例模式声明一个对象来调用非静态方法的情况是一样的,因为永远就只有这一个对象。所以访问同步方法之间一定是互斥的。

情况2:用一个类的静态对象在两个线程中调用静态方法或非静态方法

结果:会产生互斥。

解释:因为是一个对象调用,同上。都调用静态方法的时候,相当于是同一个类锁,用的都是同一个类对象。

都调用非静态方法的时候,相当于是同一个对象锁。

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

结果:不会产生互斥。

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

例子

pulbic class Something(){
  public synchronized void isSyncA(){}
  public synchronized void isSyncB(){}
  public static synchronized void cSyncA(){}
  public static synchronized void cSyncB(){}
}

那么,加入有Something类的两个实例a与b,那么下列哪组方法可以被1个以上线程同时访问呢?

a. x.isSyncA()与 x.isSyncB()
b. x.isSyncA()与 y.isSyncA()
c. x.cSyncA()与 y.cSyncB()
d. x.isSyncA()与 Something.cSyncA()

这里,很清楚的可以判断:

a,都是对同一个实例的synchronized域访问,因此不能被同时访问

b,是针对不同实例的,因此可以同时被访问

c,因为是static synchronized,所以不同实例之间不会被限制

d,书上的答案是可以被同时访问的,答案理由是synchronzied的是实例方法与synchronzied的类方法由于锁定(lock)不同的原因。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java中synchronized实现原理详解

    记得刚刚开始学习Java的时候,一遇到多线程情况就是synchronized,相对于当时的我们来说synchronized是这么的神奇而又强大,那个时候我们赋予它一个名字"同步",也成为了我们解决多线程情况的百试不爽的良药.但是,随着我们学习的进行我们知道synchronized是一个重量级锁,相对于Lock,它会显得那么笨重,以至于我们认为它不是那么的高效而慢慢摒弃它. 诚然,随着Javs SE 1.6对synchronized进行的各种优化后,synchronized并不会显得那么

  • 深入理解java内置锁(synchronized)和显式锁(ReentrantLock)

    synchronized 和 Reentrantlock 多线程编程中,当代码需要同步时我们会用到锁.Java为我们提供了内置锁(synchronized)和显式锁(ReentrantLock)两种同步方式.显式锁是JDK1.5引入的,这两种锁有什么异同呢?是仅仅增加了一种选择还是另有其因?本文为您一探究竟. // synchronized关键字用法示例 public synchronized void add(int t){// 同步方法 this.v += t; } public stati

  • JAVA面试题 简谈你对synchronized关键字的理解

    面试官:sychronized关键字有哪些特性? 应聘者: 可以用来修饰方法; 可以用来修饰代码块; 可以用来修饰静态方法; 可以保证线程安全; 支持锁的重入; sychronized使用不当导致死锁; 了解sychronized之前,我们先来看一下几个常见的概念:内置锁.互斥锁.对象锁和类锁. 内置锁 在Java中每一个对象都可以作为同步的锁,那么这些锁就被称为内置锁.线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁.获得内置锁的唯一途径就是进入这个锁的保护的同

  • 透彻理解Java中Synchronized(对象锁)和Static Synchronized(类锁)的区别

    本文讲述了Java中Synchronized(对象锁)和Static Synchronized(类锁)的区别.分享给大家供大家参考,具体如下: Synchronized和Static Synchronized区别 通过分析这两个用法的分析,我们可以理解java中锁的概念.一个是实例锁(锁在某一个实例对象上,如果该类是单例,那么该锁也具有全局锁的概念),一个是全局锁(该锁针对的是类,无论实例多少个对象,那么线程都共享该锁).实例锁对应的就是synchronized关键字,而类锁(全局锁)对应的就是

  • Java synchronized关键字和Lock接口实现原理

    这篇文章主要介绍了Java synchronized关键字和Lock接口实现原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 引用 当开发过程中,我们遇到并发问题.怎么解决? 一种解决方式,简单粗暴:上锁.将千军万马都给拦下来,只允许一个人过独木桥.书面意思就是将并行的程序变成串行的程序.现实的锁有门锁.挂锁和抽屉锁等等.在Java中,我们的锁就是synchronized关键字和Lock接口. synchronized关键字 synchron

  • java synchronized同步静态方法和同步非静态方法的异同

    java synchronized 详解 synchronized关键字有两种用法,一种是只用于方法的定义中,另外一种是synchronized块,我们不仅可以使用synchronized来同步一个对象变量,你也可以通synchronizedl来同步类中的静态方法和非静态方法. synchronized块的语法如下: public void method() { synchronized(表达式) { } } public void method() { synchronized(表达式) {

  • 基于synchronized修饰静态和非静态方法

    前言 最近被问到了这个问题,第一次回答的也是很不好,在此参考网上答案进行整理记录.供大家学习参考. Synchronized修饰非静态方法 Synchronized修饰非静态方法,实际上是对调用该方法的对象加锁,俗称"对象锁". Java中每个对象都有一个锁,并且是唯一的.假设分配的一个对象空间,里面有多个方法,相当于空间里面有多个小房间,如果我们把所有的小房间都加锁,因为这个对象只有一把钥匙,因此同一时间只能有一个人打开一个小房间,然后用完了还回去,再由JVM 去分配下一个获得钥匙的

  • PHP静态调用非静态方法的应用分析

    静态调用非静态方法!!这在java,c#中是不可想象的,也是绝对不行的.这样的错误在这些语言中会在编译阶段就被指出错误的.但是对于php这样的动态语言呢?首先这个是语法没有错误的,php –l 找不出错误来的.如果运行呢?先看一个例子 复制代码 代码如下: <?php class myClass {     private $name = "myClass"; public function echoName(){         echo $this->name;    

  • C#静态方法与非静态方法实例分析

    本文实例分析了C#静态方法与非静态方法,并对其用法进行了较为全面的分析.分享给大家供大家参考.具体分析如下: 通常来说,C#的类中可以包含两种方法:静态方法和非静态方法. 使用了static 修饰符的方法为静态方法,反之则是非静态方法. 静态方法是一种特殊的成员方法,它不属于类的某一个具体的实例,而是属于类本身.所以对静态方法不需要首先创建一个类的实例,而是采用 类名.静态方法 的格式 . 1)static方法是类中的一个成员方法,属于整个类,即不用创建任何对象也可以直接调用. static内部

  • .NET中的静态与非静态的区别分析

    静态类 vs 普通类 静态类与普通类的区别有以下几点: 1)静态类无法实例化而普通类可以: 2)静态类只能从System.Object基类继承:普通可以继承其它任何非static和非sealed类,但也只能继承一个类: 3)静态类不能继承接口:普通类可以继承多个接口: 4)静态类只能包含静态成员:普通类可以包含静态和非静态成员: 5)静态类不能作为字段,方法参数和局部变量使用:普通类可以; 静态类的意义: 可以用静态类封装一组不与任何对象相关联的方法,如Math类,Console类. 静态构造函

  • Java多线程程序中synchronized修饰方法的使用实例

    在Java 5以前,是用synchronized关键字来实现锁的功能. synchronized关键字可以作为方法的修饰符(同步方法),也可作用于函数内的语句(同步代码块). 掌握synchronized,关键是要掌握把那个东西作为锁.对于类的非静态方法(成员方法)而言,意味着要取得对象实例的锁:对于类的静态方法(类方法)而言,要取得类的Class对象的锁:对于同步代码块,要指定取得的是哪个对象的锁.同步非静态方法可以视为包含整个方法的synchronized(this) { - }代码块.  

  • c#静态方法和非静态方法详细介绍

    C#的类中可以包含两种方法:静态方法和非静态方法. 使用了static 修饰符的方法为静态方法,反之则是非静态方法. 静态方法是一种 特殊的成员方法,它不属于类的某一个具体的实例,而是属于类本身.所以对静态方法不需要 首先创建一个类的实例,而是采用类名.静态方法的格式 .1.static方法是类中的一个成员方法,属于整个类,即不用创建任何对象也可以直接调用!static内部只能出现static变量和其他static方法!而且static方法中还不能使用this....等关键字..因为它是 属于整

  • 浅析php静态方法与非静态方法的用法区别

    在php编程中,static关键字声明一个属性或方法是和类相关的,而不是和类的某个特定的实例相关,因此,这类属性或方法也称为"类属性"或"类方法" 如果访问控制权限允许,可不必创建该类对象而直接使用类名加两个冒号"::"调用. static关键字可以用来修饰变量.方法. 不经过实例化,就可以直接访问类中static的属性和static的方法. static 的属性和方法,只能访问static的属性和方法,不能类访问非静态的属性和方法.因为静态属性

  • Java基于final修饰数据过程解析

    这篇文章主要介绍了Java基于final修饰数据过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 final是Java中的一个重要关键字,它可以修饰数据.方法和类,本篇将从final修饰的数据角度对final做出总结. final修饰的数据代表着:永远不变.意思是,一旦你用final修饰一块数据,你之后就只能看看它,你想修改它,没门. 我们不希望改变的数据有下面两种情况: 永不改变的编译时常量. //编译时知道其值 private fin

  • Java 中的静态字段和静态方法 

    目录 一.静态变量 静态变量声明 静态变量测试 二.静态方法 静态方法测试 静态方法是如何工作的 为什么 Java Main 方法是静态方法 三.静态常量 四.总结 先看看下面这一串代码: public class Main {     public static void main(String[] args) {         System.out.println("Hello, WOrld!");     } } 我们的 ​​main​​ 方法被标记了 ​​static​​ 修

随机推荐