【问题描述】关于Java中synchronized 用在实例方法和对象方法上面的区别
【问题分析】大家都知道,在Java中,synchronized 是用来表示同步的,我们可以synchronized 来修饰一个方法(实例方法和类方法---注:不知道这样叫准确不准确,大家理解我的意识就行了)。也可以synchronized 来修饰方法里面的一个语句块。
修饰实例方法:
- public synchronized void x() throws InterruptedException
- {
- for (int i = 0; i < 10; i++)
- {
- Thread.sleep(1000);
- System.out.println("x.......................");
- }
- }
修饰类方法(static 方法):
- public static synchronized void staticX() throws InterruptedException
- {
- for (int i = 0; i < 10; i++)
- {
- Thread.sleep(1000);
- System.out.println("staticX.......................");
- }
- }
修饰方法里面语句块:
- public static void staticX() throws InterruptedException
- {
- synchronized (locks)
- {
- for (int i = 0; i < 10; i++)
- {
- Thread.sleep(1000);
- System.out.println("staticX.......................");
- }
- }
- }
注意:这里不能用synchronized修饰方法外面的语句块(我把他叫做类语句块),虽然我们可以在方法外面定义语句块,这样做会遇到编译错误,这里涉及到了Java里面的对象初始化的部分知识。大概的原因就是synchronized锁住的是对象,当初始化对象的时候,JVM在对象初始化完成之前会调用方法外面的语句块,这个时候对象还不存在,所以就不存在锁了。
那么,在static方法和非static方法前面加synchronized到底有什么不同呢?
大家都知道,static的方法属于类方法,它属于这个Class(注意:这里的Class不是指Class的某个具体对象),那么static获取到的锁,就是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。而非static方法获取到的锁,就是当前调用这个方法的对象的锁了。所以,他们之间不会产生互斥。
看代码:
- package com.jack.zhang.chapter9.classlock;
- /**
- * @author Jack Zhang
- * @version vb1.0
- * @Email virgoboy2004@163.com
- * @Date 2012-5-20
- */
- public class Test
- {
- public static synchronized void staticX() throws InterruptedException
- {
- for (int i = 0; i < 10; i++)
- {
- Thread.sleep(1000);
- System.out.println("staticX.......................");
- }
- }
- public synchronized void x() throws InterruptedException
- {
- for (int i = 0; i < 10; i++)
- {
- Thread.sleep(1000);
- System.out.println("x.......................");
- }
- }
- public static void main(String[] args)
- {
- final Test test1 = new Test();
- Thread thread = new Thread(new Runnable()
- {
- public void run()
- {
- try
- {
- test1.x();
- }
- catch (InterruptedException e)
- {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }, "a");
- Thread thread1 = new Thread(new Runnable()
- {
- public void run()
- {
- try
- {
- Test.staticX();
- }
- catch (InterruptedException e)
- {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }, "b");
- thread1.start();
- thread.start();
- }
- }
运行结果是:
- staticX.......................
- x.......................
- x.......................
- staticX.......................
- staticX.......................
- x.......................
- x.......................
- staticX.......................
- x.......................
- staticX.......................
- staticX.......................
- x.......................
- x.......................
- staticX.......................
- x.......................
- staticX.......................
- x.......................
- staticX.......................
- x.......................
- staticX.......................
那当我们想让所有这个类下面的对象都同步的时候,也就是让所有这个类下面的对象共用同一把锁的时候,我们如何办呢?
看代码:
- package com.jack.zhang.chapter9.classlock;
- /**
- * @author Jack Zhang
- * @version vb1.0
- * @Email virgoboy2004@163.com
- * @Date 2012-5-20
- */
- public class Test
- {
- public final static Byte[] locks = new Byte[0];
- public static void staticX() throws InterruptedException
- {
- synchronized (locks)
- {
- for (int i = 0; i < 10; i++)
- {
- Thread.sleep(1000);
- System.out.println("staticX.......................");
- }
- }
- }
- public void x() throws InterruptedException
- {
- synchronized (locks)
- {
- for (int i = 0; i < 10; i++)
- {
- Thread.sleep(1000);
- System.out.println("x.......................");
- }
- }
- }
- public static void main(String[] args)
- {
- final Test test1 = new Test();
- final Test test2 = new Test();
- Thread thread = new Thread(new Runnable()
- {
- public void run()
- {
- try
- {
- test1.x();
- }
- catch (InterruptedException e)
- {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }, "a");
- Thread thread1 = new Thread(new Runnable()
- {
- public void run()
- {
- try
- {
- Test.staticX();
- }
- catch (InterruptedException e)
- {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }, "b");
- thread1.start();
- thread.start();
- }
- }
运行结果:
- staticX.......................
- staticX.......................
- staticX.......................
- staticX.......................
- staticX.......................
- staticX.......................
- staticX.......................
- staticX.......................
- staticX.......................
- staticX.......................
- x.......................
- x.......................
- x.......................
- x.......................
- x.......................
- x.......................
- x.......................
- x.......................
- x.......................
- x.......................
相关推荐
在 Java 中,synchronized 关键字可以作用于 instance 变量、object reference(对象引用)、static 函数和 class literals(类名称字面常量)身上。 Synchronized 关键字的作用是取得对象的锁,而不是把一段代码或...
Java 语言中的修饰词可以用来控制成员的访问权限、确保类和方法的不可变性、定义抽象类和抽象方法、调用 native 库、确保浮点计算的精度和可移植性、确保多线程环境中的安全执行等等。正确地使用修饰词可以提高 Java...
Java 中 Synchronized(对象锁)和 Static Synchronized(类锁)的区别 Synchronized 和 Static Synchronized 是 Java 中两种同步机制,它们都用于解决多线程并发访问的安全问题。然而,它们之间存在着本质的区别。...
当一个非静态方法被synchronized修饰时,该方法被称为同步方法。同步方法通过对象锁进行保护,同一时刻,只有一个线程能够访问该对象的同步方法。例如: ```java public class Test { public synchronized void ...
Java 访问修饰符是 Java 编程语言中的一种重要机制,它控制着类、方法和变量的访问权限。访问修饰符可以分为四种:public、protected、private 和缺省(无访问修饰符)。 public 访问修饰符 public 访问修饰符是最...
Java中的`synchronized`关键字是用于实现线程同步的关键机制,它的主要目的是确保在多线程环境中,对共享资源的访问能够正确地按照预定顺序进行,防止数据不一致性和线程安全问题。本篇将深入探讨`synchronized`修饰...
本文将深入解析`synchronized`在Java中的应用和工作原理。 一、`synchronized`的基本用法 `synchronized`可以应用于方法或代码块。当它修饰一个方法时,整个方法被视为同步的,只有一个线程可以执行该方法。当修饰...
在Java中,某些修饰符可以组合使用,如`public static`、`protected final`等,以达到更精细的控制效果。例如,`public static`方法表示该方法是公共的且与类实例无关,而`protected final`变量则表示受保护的且不可...
JAVA 访问修饰符是 JAVA 语言中的一种基本概念,它控制着类、方法、变量的访问权限,帮助开发者更好地组织和管理代码。根据 JAVA 访问修饰符的特性和使用范围,我们可以将其分为三类:修饰符类的访问修饰符、属性的...
本文将详细介绍Java中常见的修饰符及其用途。 1. **类的修饰符** - **public**: 公共访问控制符,允许任何地方的任何类访问。Java程序的主类必须是public,以便作为程序的入口点。 - **abstract**: 抽象类修饰符...
以下是对Java中11个修饰词的详细介绍: 1. **public**: - 使用对象:类、接口、成员 - 介绍:`public`修饰符使得类、接口或成员对所有其他类可见,无论它们是否位于同一包内。这意味着,只要拥有相应的引用,...
1. 无论 synchronized 关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁。 2. 每个对象只有一个锁(lock)与之相关联。 3. 实现同步是要很大的系统开销作为代价的,甚至可能造成死锁...
本文将深入探讨`synchronized`关键字在同步静态方法和非静态方法上的异同。 首先,`synchronized`关键字有两种主要的使用方式:一是修饰方法,二是作为代码块。当`synchronized`修饰一个非静态方法时,锁住的是该...
以上就是Java中主要的修饰符及其作用,理解并熟练运用这些修饰符是编写高质量、安全、可维护的Java代码的关键。在实际编程中,合理选择和组合这些修饰符可以帮助我们更好地控制代码的结构和行为。
同步方法是通过在方法声明前加上`synchronized`关键字实现的。这样,同一时间只有一个线程可以执行该方法。例如: ```java public class Counter { private int count = 0; public synchronized void increment...
可以通过在方法声明前加上`synchronized`关键字来创建同步方法,例如: ```java public synchronized void method() { // 方法体 } ``` 对于静态方法,可以使用`synchronized`关键字修饰类名,例如: ```java ...
synchronized 静态方法修饰一个 static 静态方法,其作用范围是整个静态方法,作用对象是这个类的全部对象。synchronized 类,其作用范围是 Synchronized 后面括号括起来的部分 synchronized(className.class),作用...
以下是对Java中11种主要修饰词的详细解释: 1. **public**: - `public`修饰的类、接口和成员可以在任何地方被访问,没有访问限制。 - 通常用于创建需要跨包共享的类或接口。 2. **private**: - `private`修饰...
在Java中,修饰符分为两类:访问修饰符和非访问修饰符。这里我们将详细介绍这两种类型,并着重讲解访问修饰符的使用。 1. 访问修饰符: - **default**(默认):在类、接口、变量和方法的定义中没有指定任何访问...