`

探讨Java中static synchronized和synchronized

 
阅读更多

探讨Java中static synchronized和synchronized

 

synchronized提供内部锁的机制,防止其它线程同时进入synchronized的代码块。synchronized由两部分组成:1.锁对象的引用;2.锁保护的代码块。

对锁对象引用的不同,是static synchronized和synchronized最大的区别:

复制代码
 1 public class SynchronizedTester {
 2 
 3     /*
 4      * testOne()和testTwo()均是对SynchronizedTester这个类的对象(实例)加上锁
 5      * 也就是锁对象的引用是SynchronizedTester这个类的对象(实例)
 6      * 两种写法基本等价
 7      */
 8     private synchronized void testOne(){
 9         //do something...
10     }
11     private void testTwo(){
12         synchronized(this){
13             //do something...
14         }
15     }
16 
17 }
复制代码
复制代码
 1 public class SynchronizedStaticTester {    
 2     /*
 3      * testOne()和testTwo()则是对SynchronizedTester这个类加上锁
 4      * 也就是锁对象的引用是SynchronizedTester这个类,不再是类的对象或类的实例
 5      * 两种写法基本等价
 6      */
 7     private static synchronized void testOne(){
 8         //do sth.
 9     }
10     
11     private static void testTwo(){
12         synchronized (SynchronizedStaticTester.class) { //Notice: Not this!
13             // do sth.
14         }
15     }
16     
17     
18 
19 }
复制代码

synchronized的范围是某个类的对象/实例,防止多个线程同时访问同一个类对象/实例的synchronized代码块。

static synchronized地方范围是某个类,防止多个线程同时访问这个类的synchronized代码块。

知道区别以后看看题目:

1.出自并发编程网

按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

问题:

  1. 线程1访问A.staticWrite(true)方法时,线程2能访问A.staticRead()方法吗?
  2. 线程1访问new A().staticWrite(false)方法时,线程2能访问new A().staticRead()方法吗?
  3. 线程1访问A.staticWrite(false)方法时,线程2能访问new A().staticRead()方法吗?

答案是都不能。因为无论A创建多少个对象或实例,任一对象调用staticWrite(),或类直接调用staticWrite(),锁对象的引用都是A.class。也就是只要调用staticWrite方法,都会对A.class加锁,而staticRead()需要获得的锁对象也正是A.class,因此会出现阻塞。所以线程2无法访问A.staticRead()方法。

  1. A a=new A(); 线程1访问a.write(false)方法,线程2能访问a.read()方法吗?
  2. A a=new A(); A b=new A();线程1访问a.write(false)方法,线程2能访问b.read()方法吗?

题目1答案是不可以,理由与上面类似。a.write()对类A的对象a加了锁,而a.read()需要获得的锁对象也刚好是a,所以线程2无法访问a.read()

题目2答案是可以,a.write()对类A的对象加了锁,而b.read()需要获得的锁对象则是b,两者无冲突。b.read()能顺利获得锁,并访问read()方法。

再次总结:

  1. 对于实例同步方法,锁是当前实例对象。
  2. 对于静态同步方法,锁是当前对象的Class对象。
  3. 对于同步方法块,锁是Synchonized括号里配置的对象。

 

再看一题,出自日本作者-结成浩的《java多线程设计模式》

1 pulbic class Something(){
2          public synchronized void isSyncA(){}
3          public synchronized void isSyncB(){}
4          public static synchronized void cSyncA(){}
5          public static synchronized void cSyncB(){}
6      }

有Something类的两个实例x与y,那么下列组方法何以被1个以上线程同时访问呢
   a.   x.isSyncA()与x.isSyncB() 
   b.   x.isSyncA()与y.isSyncA()
   c.   x.cSyncA()与y.cSyncB()
   d.   x.isSyncA()与Something.cSyncA()

有了上面的知识,很容易判断a,c不能,而b可以。d稍微分析一下,也可以确定可以被1个以上线程同时访问,因此x.isSyncA()锁的是Something的对象x,而Something.cSyncA()锁的是Something.class。

最后要留意的是:synchronized并不能继承,子类覆盖父类synchronized方法时,一定也要在前面加上synchronized关键字;但子类未重写该方法,实例化子类,调用对应方法,也会加锁

这篇文章对synchronized关键字做了深入的总结,值得仔细理解。

分享到:
评论

相关推荐

    深入理解java中的synchronized关键字

    Java中的`synchronized`关键字是用于实现线程同步的关键机制,它的主要目的是确保在多线程环境中,对共享资源的访问能够保持数据的一致性和完整性。本文将深入探讨`synchronized`的两种主要用法:synchronized方法和...

    Java并发-Synchronized关键字.docx

    总的来说,`synchronized`关键字是Java中解决并发问题的基本手段之一,它通过保证代码的原子性、可见性和有序性,确保了多线程环境下的数据安全性。但在实际开发中,我们需要根据具体场景权衡其性能和功能,选择最...

    synchronized的几种示例

    总结来说,`synchronized`关键字在Java中提供了线程安全的保证,通过方法加锁、代码块加锁和静态方法加锁,我们可以根据需求选择合适的同步策略。正确使用`synchronized`可以避免竞态条件和死锁等问题,从而保证多...

    synchronized与单例的线程安全

    synchronized是Java中的一个关键同步机制,用于控制对类或对象的并发访问。它有两种使用方式:方法同步和代码块同步。 1. 方法同步:通过在方法声明前加上`synchronized`关键字,整个方法体将被锁定,一次只有一个...

    synchronized枷锁实例

    在Java编程语言中,`synchronized`关键字是一个非常重要的同步机制,用于控制多线程对共享资源的访问,以防止数据不一致性和竞态条件。本文将深入探讨`synchronized`关键字的用法,包括类锁、对象锁、方法锁以及它们...

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

    本篇将深入探讨`synchronized`修饰方法在Java多线程程序中的使用实例。 1. **同步方法** 同步方法是通过在方法声明前加上`synchronized`关键字来实现的。当一个方法被声明为同步时,意味着在同一时刻只有一个线程...

    Java Thread in JVM

    本文将深入探讨Java Thread的语法特性以及其在JVM内部的编译结果,帮助开发者更好地理解和使用线程。 1. **synchronized方法的Java语言规范** `synchronized`关键字用于控制多线程对共享资源的访问,以确保线程...

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

    本文将深入探讨`synchronized`关键字在同步静态方法和非静态方法上的异同。 首先,`synchronized`关键字有两种主要的使用方式:一是修饰方法,二是作为代码块。当`synchronized`修饰一个非静态方法时,锁住的是该...

    JAVA多线程编程技术探讨.pdf

    本文主要探讨了JAVA多线程编程技术的基础,特别是线程的创建方法、线程管理和线程同步处理技术。关键词包括:JAVA、多线程、创建、管理、同步。 #### 前言 在多线程编程中,可以通过分配不同的线程来执行不同的任务...

    Java 模拟线程并发

    Java 模拟线程并发是编程领域中的一个重要概念,尤其在多核处理器和高并发应用中,理解并熟练掌握线程并发技术对于提升程序性能至关重要。在Java中,线程并发可以通过多种方式实现,包括继承Thread类、实现Runnable...

    关于Java多线程机制的探讨.pdf

    "Java多线程机制探讨" Java多线程机制是指在Java语言中实现多线程编程的机制。多线程机制允许多个线程同时执行,提高了程序的效率和响应速度。Java多线程机制可以通过Thread类或Runnable接口实现。 Thread类是Java...

    java多线程之线程,进程和Synchronized概念初解

    本文主要探讨了线程、进程以及Java中实现多线程的方法,并着重讲解了线程安全和`synchronized`关键字的使用。 首先,理解进程与线程的概念至关重要。进程是操作系统资源分配的基本单位,它包含了一个程序的运行环境...

    MLDN魔乐JAVA_11程序分析、单例设计、static相关应用.rar

    在本资源"MLDN魔乐JAVA_11程序分析、单例设计、static相关应用.rar"中,我们探讨了三个核心的Java编程概念:程序分析、单例设计模式以及静态(static)关键字的应用。这些都是Java开发者必备的知识点,对于理解和...

    【技术分享】Java中的那些“锁”事.pptx

    本文将深入探讨Java中的锁以及相关的线程安全数据结构。 首先,我们来理解什么是锁。在多线程环境下,当多个线程试图访问和修改同一份共享数据时,为了防止数据的不一致性,引入了锁的概念。锁的主要作用是提供一种...

    Java单例模式设计

    本篇文章将深入探讨Java中的三种单例实现方式:饿汉单例、懒汉单例以及序列化与反序列化对单例的影响。 **1. 饿汉单例模式** 饿汉单例在类加载时就完成了初始化,因此是线程安全的。它的实现方式通常使用静态常量...

    java中线程的简单处理

    本篇将深入探讨Java中线程的简单处理。 首先,我们可以通过实现`Runnable`接口来创建一个线程。以下是一个基本的示例: ```java class MyRunnable implements Runnable { public void run() { // 在这里编写线程...

    java基础,javacode

    在这个主题下,我们将深入探讨Java的基础知识,包括语法、类、对象、数据类型、控制结构、异常处理以及一些核心概念。 1. **Java语法基础** Java语法基于C++,但更加简洁和安全。每个Java程序都从`public class`...

    Java同步机制浅谈

    本篇文章将深入探讨`synchronized`关键字的工作原理、使用方式以及在实际开发中的应用技巧。 #### 一、synchronized关键字的基础概念 `synchronized`关键字主要用于解决Java应用程序中的多线程同步问题。它可以...

    java单例模式实例

    在Java中,有多种实现单例模式的方法,每种都有其特点和适用场景。接下来,我们将深入探讨这些实现方式。 首先,我们来看**懒汉式(Lazy Initialization)**。这种实现方式是在类被首次请求时才创建单例对象,延迟...

Global site tag (gtag.js) - Google Analytics