在Java中,synchronized 是用来表示同步的,我们可以synchronized 来修饰一个方法。也可以synchronized 来修饰方法里面的一个语句块。
修饰实例方法:
public synchronized void normalMethod() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("normalMethod:" + i); } }
修饰类方法(static 方法):
public static synchronized void staticMethod() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(500); System.out.println("staticMethod:" + i); } }
修饰方法里面语句块:
public static void staticMethod() throws InterruptedException { synchronized (locks) { for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("staticMethod:" + i); } } }
注意:这里不能用synchronized修饰方法外面的语句块(我把他叫做类语句块),虽然我们可以在方法外面定义语句块,这样做会遇到编译错误,这里涉及到了Java里面的对象初始化的部分知识。大概的原因就是synchronized锁住的是对象,当初始化对象的时候,JVM在对象初始化完成之前会调用方法外面的语句块,这个时候对象还不存在,所以就不存在锁了。
那么,在static方法和非static方法前面加synchronized到底有什么不同呢?
static的方法属于类方法,它属于这个Class(注意:这里的Class不是指Class的某个具体对象),那么static获取到的锁,就是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。而非static方法获取到的锁,就是当前调用这个方法的对象的锁了。所以,他们之间不会产生互斥。
实例1:
package com.bijian.thread; public class SynchronizedTest { public static synchronized void staticMethod() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(500); System.out.println("staticMethod:" + i); } } public synchronized void normalMethod() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("normalMethod:" + i); } } public static void main(String[] args) { final SynchronizedTest synchronizedTest = new SynchronizedTest(); Thread thread = new Thread(new Runnable() { public void run() { try { synchronizedTest.normalMethod(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "a"); Thread thread1 = new Thread(new Runnable() { public void run() { try { SynchronizedTest.staticMethod(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "b"); thread1.start(); thread.start(); } }
运行结果:
staticMethod:0 normalMethod:0 staticMethod:1 staticMethod:2 normalMethod:1 staticMethod:3 staticMethod:4 normalMethod:2 staticMethod:5 staticMethod:6 normalMethod:3 staticMethod:7 staticMethod:8 normalMethod:4 staticMethod:9 normalMethod:5 normalMethod:6 normalMethod:7 normalMethod:8 normalMethod:9
那当我们想让所有这个类下面的对象都同步的时候,也就是让所有这个类下面的对象共用同一把锁的时候,我们如何办呢?
法1:将normalMethod方法也改成static,这样这两个static方法都属于类方法,它们获取到的锁都是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。但这样会影响代码结构和对象的封装性。
修改实例1如下:
package com.bijian.thread; public class SynchronizedTest { public static synchronized void staticMethod() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(500); System.out.println("staticMethod:" + i); } } public static synchronized void normalMethod() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("normalMethod:" + i); } } public static void main(String[] args) { Thread thread = new Thread(new Runnable() { public void run() { try { SynchronizedTest.normalMethod(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "a"); Thread thread1 = new Thread(new Runnable() { public void run() { try { SynchronizedTest.staticMethod(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "b"); thread1.start(); thread.start(); } }
运行结果:
staticMethod:0 staticMethod:1 staticMethod:2 staticMethod:3 staticMethod:4 staticMethod:5 staticMethod:6 staticMethod:7 staticMethod:8 staticMethod:9 normalMethod:0 normalMethod:1 normalMethod:2 normalMethod:3 normalMethod:4 normalMethod:5 normalMethod:6 normalMethod:7 normalMethod:8 normalMethod:9
也许有人说:将实例1的staticMethod方法改成的static去掉也能达到目的。确实可以,因为非static方法获取到的锁,就是当前调用这个方法的对象的锁,而实例1只有一个SynchronizedTest实例,如再创建一个实例,则就有问题了。如下所示:
package com.bijian.thread; public class SynchronizedTest { public synchronized void staticMethod() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(500); System.out.println("staticMethod:" + i); } } public synchronized void normalMethod() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("normalMethod:" + i); } } public static void main(String[] args) { final SynchronizedTest synchronizedTest = new SynchronizedTest(); Thread thread = new Thread(new Runnable() { public void run() { try { synchronizedTest.normalMethod(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "a"); //为了验证获取到的锁都是当前调用这个方法的对象所属的类,特另新建一个对象 final SynchronizedTest synchronizedTest2 = new SynchronizedTest(); Thread thread1 = new Thread(new Runnable() { public void run() { try { synchronizedTest2.staticMethod(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "b"); thread1.start(); thread.start(); } }
运行结果:
staticMethod:0 staticMethod:1 normalMethod:0 staticMethod:2 staticMethod:3 normalMethod:1 staticMethod:4 staticMethod:5 normalMethod:2 staticMethod:6 normalMethod:3 staticMethod:7 staticMethod:8 normalMethod:4 staticMethod:9 normalMethod:5 normalMethod:6 normalMethod:7 normalMethod:8 normalMethod:9
法2:语句块锁,直接看如下实例:
实例2:
package com.bijian.thread; public class SynchronizedTest { public final static Byte[] locks = new Byte[0]; public static void staticMethod() throws InterruptedException { synchronized(locks) { for (int i = 0; i < 10; i++) { Thread.sleep(500); System.out.println("staticMethod:" + i); } } } public void normalMethod() throws InterruptedException { synchronized(locks) { for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("normalMethod:" + i); } } } public static void main(String[] args) { final SynchronizedTest synchronizedTest = new SynchronizedTest(); Thread thread = new Thread(new Runnable() { public void run() { try { synchronizedTest.normalMethod(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "a"); Thread thread1 = new Thread(new Runnable() { public void run() { try { SynchronizedTest.staticMethod(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "b"); thread1.start(); thread.start(); } }
运行结果:
staticMethod:0 staticMethod:1 staticMethod:2 staticMethod:3 staticMethod:4 staticMethod:5 staticMethod:6 staticMethod:7 staticMethod:8 staticMethod:9 normalMethod:0 normalMethod:1 normalMethod:2 normalMethod:3 normalMethod:4 normalMethod:5 normalMethod:6 normalMethod:7 normalMethod:8 normalMethod:9
相关推荐
- **对象锁**:如果`synchronized`修饰非静态方法或者同步语句块中的对象引用是实例引用,那么锁定的是该实例对象。例如: ```java public class MyObject { public synchronized void method() { // ... } }...
在上面的例子中,synchronized 关键字被用于 myMethod 方法上,以防止多个线程同时访问同一个对象的 myMethod 方法。 2. 类范围:synchronized 关键字也可以被用于类范围内,以防止多个线程同时访问同一个类中的...
Java中的`synchronized`关键字是多线程编程中的一个重要概念,用于控制并发访问共享资源,以保证数据的一致性和完整性。这个关键词提供了互斥锁机制,防止多个线程同时执行同一段代码,确保了线程安全。 一、`...
同步方法是通过在方法声明前加上`synchronized`关键字,例如`public synchronized void method() {...}`。同步代码块则是通过`synchronized`关键字包裹一段代码,如`synchronized (object) { ... }`,这里的`object`...
在上面的代码示例中,我们可以看到,Synchronized 和 Static Synchronized 的使用场景不同。Synchronized 是用于锁定当前对象的实例,而 Static Synchronized 是用于锁定该类的所有实例。 在多线程中,如果我们使用...
总结,`synchronized`是Java中实现线程安全的关键工具,理解其工作原理和使用方式对于编写高效、安全的多线程程序至关重要。然而,在实际应用中,我们需要根据具体场景选择最合适的并发控制手段,平衡性能和安全性。
通过在方法或代码块上使用`synchronized`,可以确保同一时间只有一个线程能访问这些代码区域,从而有效避免了多线程环境下的数据竞争和不一致性问题。 #### 二、synchronized的作用机制 `synchronized`主要通过对象...
在Java编程语言中,`synchronized`关键字是一个非常重要的同步机制,用于控制多线程对共享资源的访问,以防止数据不一致性和竞态条件。本文将深入探讨`synchronized`关键字的用法,包括类锁、对象锁、方法锁以及它们...
在 Account 类中,我们使用了 synchronized 来同步 deposit 和 withdraw 方法,以确保在同一时间只有一个线程可以访问这些方法。这样可以防止多个线程同时访问 Account 对象的 amount 变量,避免数据不一致和 race ...
但是,很多开发者对 synchronized 关键字的理解并不够深入,本文将通过实例解析 Java 中的 synchronized 关键字与线程平安问题,帮助开发者更好地理解和使用 synchronized 关键字。 首先,需要清晰的是 ...
在Java编程语言中,`...总结,`java synchronized demo`是一个关于如何在Java中使用`synchronized`关键字进行线程同步的示例,通过理解和实践这个例子,开发者可以更好地掌握多线程环境下数据安全和同步的重要性。
《Java面向对象编程》实例源代码是一份宝贵的教育资源,它涵盖了Java编程中面向对象的核心概念。这份资源由知名教育机构飞思出品,旨在帮助学习者深入理解和应用面向对象编程技术。通过这些源代码实例,我们可以深入...
Java中的`synchronized`关键字是用于实现线程同步的关键机制,它的主要目的是确保在多线程环境中,对共享资源的访问能够保持数据的一致性和完整性。本文将深入探讨`synchronized`的两种主要用法:synchronized方法和...
本文将深入解析`synchronized`在Java中的应用和工作原理。 一、`synchronized`的基本用法 `synchronized`可以应用于方法或代码块。当它修饰一个方法时,整个方法被视为同步的,只有一个线程可以执行该方法。当修饰...
本文将深入探讨synchronized修饰方法在Java中的使用及其工作原理,并通过实例演示其应用。 1. **synchronized原理** synchronized基于Java的内置锁(也称为对象锁或 monitors)机制。当一个线程进入synchronized...
1. 同步方法:在方法声明前加上`synchronized`关键字,使得每次只有一个线程能执行该方法。 ```java public synchronized void method() { // 方法体 } ``` 2. 同步代码块:锁定对象实例,只允许一个线程访问指定的...
在售票示例中,我们可以用`this`作为监视器对象,因为它代表当前类的实例: ```java public void run() { for (int i = 0; i ; i++) { if (this.ticket > 0) { synchronized (this) { // 休眠1s try { ...
本篇将深入探讨`synchronized`修饰方法在Java多线程程序中的使用实例。 1. **同步方法** 同步方法是通过在方法声明前加上`synchronized`关键字来实现的。当一个方法被声明为同步时,意味着在同一时刻只有一个线程...
Java中的`synchronized`关键字是多线程编程中的一个重要概念,用于控制并发访问共享资源,确保数据的正确性和一致性。在Java中,同步可以应用于方法或代码块,为线程提供互斥访问,防止数据竞争问题。 1. **什么是`...
Java 中的 synchronized 关键字是用来实现线程同步的,它可以用来修饰方法、代码块和静态方法,以确保在多线程环境下数据的一致性。 一、进程和线程的区别 在计算机中,每个运行着的 xxxx.exe 都是一个进程,而...