synchronized是Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
对synchronized(this)的一些理解:
一、当两个并发线程访问同一个object中的synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object所有同步代码的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用。
举例说明:
一、当两个并发线程访问同一个object中的synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
public class Thread1 implements Runnable { public void run() { synchronized (this) { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + " synchronized loop " + i); } } } public static void main(String[] args) { Thread1 t1 = new Thread1(); Thread ta = new Thread(t1, "A"); Thread tb = new Thread(t1, "B"); ta.start(); tb.start(); } }
结果:
A synchronized loop 0
A synchronized loop 1
A synchronized loop 2
A synchronized loop 3
A synchronized loop 4
B synchronized loop 0
B synchronized loop 1
B synchronized loop 2
B synchronized loop 3
B synchronized loop 4
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
public class Thread2 { public void m4t1() { synchronized (this) { int i = 5; while (i-- > 0) { System.out .println(Thread.currentThread().getName() + " : " + i); try { Thread.sleep(500); } catch (InterruptedException ie) { } } } } public void m4t2() { int i = 5; while (i-- > 0) { System.out.println(Thread.currentThread().getName() + " : " + i); try { Thread.sleep(500); } catch (InterruptedException ie) { } } } public static void main(String[] args) { final Thread2 myt2 = new Thread2(); Thread t1 = new Thread(new Runnable() { public void run() { myt2.m4t1(); } }, "t1"); Thread t2 = new Thread(new Runnable() { public void run() { myt2.m4t2(); } }, "t2"); t1.start(); t2.start(); } }
结果:
t1 : 4
t2 : 4
t1 : 3
t2 : 3
t1 : 2
t2 : 2
t1 : 1
t2 : 1
t1 : 0
t2 : 0
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
//修改Thread2.m4t2()方法: public void m4t2() { synchronized (this) { int i = 5; while (i-- > 0) { System.out.println(Thread.currentThread().getName() + " : " + i); try { Thread.sleep(500); } catch (InterruptedException ie) { } } } }
结果:
t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object所有同步代码的访问都被暂时阻塞。
//修改Thread2.m4t2()方法如下: public synchronized void m4t2() { int i = 5; while (i-- > 0) { System.out.println(Thread.currentThread().getName() + " : " + i); try { Thread.sleep(500); } catch (InterruptedException ie) { } } }
结果:
t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0
五、以上规则对其它对象锁同样适用:
public class Thread3 { class Inner { private void m4t1() { int i = 5; while (i-- > 0) { System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i); try { Thread.sleep(500); } catch (InterruptedException ie) { } } } private void m4t2() { int i = 5; while (i-- > 0) { System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i); try { Thread.sleep(500); } catch (InterruptedException ie) { } } } } private void m4t1(Inner inner) { synchronized (inner) { // 使用对象锁 inner.m4t1(); } } private void m4t2(Inner inner) { inner.m4t2(); } public static void main(String[] args) { final Thread3 myt3 = new Thread3(); final Inner inner = myt3.new Inner(); Thread t1 = new Thread(new Runnable() { public void run() { myt3.m4t1(inner); } }, "t1"); Thread t2 = new Thread(new Runnable() { public void run() { myt3.m4t2(inner); } }, "t2"); t1.start(); t2.start(); } }
结果:
t1 : Inner.m4t1()=4
t2 : Inner.m4t2()=4
t2 : Inner.m4t2()=3
t1 : Inner.m4t1()=3
t2 : Inner.m4t2()=2
t1 : Inner.m4t1()=2
t1 : Inner.m4t1()=1
t2 : Inner.m4t2()=1
t2 : Inner.m4t2()=0
t1 : Inner.m4t1()=0
尽管线程t1获得了对Inner的对象锁,但由于线程t2访问的是同一个Inner中的非同步部分。所以两个线程互不干扰。
现在在Inner.m4t2()前面加上synchronized:
private synchronized void m4t2() { int i = 5; while (i-- > 0) { System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i); try { Thread.sleep(500); } catch (InterruptedException ie) { } } }
结果:
t1 : Inner.m4t1()=4
t1 : Inner.m4t1()=3
t1 : Inner.m4t1()=2
t1 : Inner.m4t1()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=4
t2 : Inner.m4t2()=3
t2 : Inner.m4t2()=2
t2 : Inner.m4t2()=1
t2 : Inner.m4t2()=0
尽管线程t1与t2访问了同一个Inner对象中两个毫不相关的部分,但因为t1先获得了对Inner的对象锁,所以t2对Inner.m4t2()的访问也被阻塞,因为m4t2()是Inner中的一个同步方法。
相关推荐
所以,当线程1调用a1.func()而线程2调用a2.func()时,这两个线程可以并发执行,因为它们分别在不同的对象实例上进行操作,互不影响。 然而,如果两个线程试图访问同一对象实例的`synchronized`方法,情况就会有所...
"Java 中 synchronized 用法详解" Synchronized 是 Java 语言中用于解决多线程共享数据同步问题的关键字。它可以作为函数的修饰符,也可以作为函数内的语句,用于实现同步方法和同步语句块。在 Java 中,...
1. 同步方法:在方法声明前加上`synchronized`关键字,使得每次只有一个线程能执行该方法。 ```java public synchronized void method() { // 方法体 } ``` 2. 同步代码块:锁定对象实例,只允许一个线程访问指定的...
1. 对象实例范围:synchronized 关键字可以被用于对象实例的方法上,以防止多个线程同时访问同一个对象的 synchronized 方法。例如: ```java public class MyClass { public synchronized void myMethod() { // ....
1. **方法同步**:在方法声明前加上`synchronized`,整个方法都会被锁定,任何时刻只有一个线程能执行该方法。 ```java public synchronized void method() { // 方法体 } ``` 2. **代码块同步**:锁定特定对象,...
1. **应用范围**:`volatile`只能应用于变量级别,而`synchronized`可以应用于变量、方法甚至是代码块级别。 2. **性能差异**:通常情况下,`volatile`的性能优于`synchronized`。这是因为`synchronized`会导致线程...
在Java编程语言中,`synchronized`关键字是一个重要的并发控制机制,用于确保多线程环境下的数据一致性。本文将深入探讨`synchronized`的几种使用示例,包括方法加锁、代码块加锁(针对`this`和对象)以及静态方法...
"Java 锁机制 Synchronized" Java 锁机制 Synchronized 是 Java 语言中的一种同步机制,用于解决多线程并发访问共享资源时可能出现的一些问题。 Java 锁机制 Synchronized 的概念 在 Java 中,每个对象都可以被...
A synchronized loop 1 A synchronized loop 2 A synchronized loop 3 A synchronized loop 4 B synchronized loop 0 B synchronized loop 1 B synchronized loop 2 B synchronized loop 3 B synchronized loop 4 ``...
- **解释**:线程`A`和线程`B`共享同一个`Thread1`实例`t1`,因此当线程`A`获取到`t1`的锁并执行`synchronized(this)`内的代码时,线程`B`将被阻塞,直到线程`A`释放锁。 2. **同步代码块与非同步代码块的访问** ...
1. **同步实例方法**: ```java public class Counter { private int count = 0; public synchronized void increment() { count++; } } ``` 在上面的例子中,`increment()`方法被`synchronized`修饰,这...
### 1. 同步方法 同步方法是通过在方法声明前加上`synchronized`关键字实现的。这样,同一时间只有一个线程可以执行该方法。例如: ```java public class Counter { private int count = 0; public ...
1. **synchronized的两种使用方式** - **方法同步**:在方法声明前加上`synchronized`关键字,这将使得整个方法成为同步方法,每次只有一个线程可以执行该方法。 ```java public synchronized void someMethod...
**1. synchronized的两种用法** - **方法级别同步:** 可以通过在方法声明前加上`synchronized`关键字来同步整个方法。这将确保每次只有一个线程可以调用该方法。 ```java public synchronized void method() { /...
1. **同步代码块**:可以通过`synchronized`关键字来声明同步代码块,即通过指定对象锁来实现同步。 ```java synchronized (object) { // 需要同步执行的代码 } ``` - 这种方式中,`object`对象作为锁,任何...
在这个示例中,`Thread1`类实现了`Runnable`接口,并在`run`方法中定义了一个`synchronized(this)`代码块。当两个线程`A`和`B`分别启动时,它们都将尝试执行该同步代码块。根据`synchronized`的特性,一次只有一个...
在深入探讨`synchronized`的关键知识点之前,我们先来明确`synchronized`在Java中的核心作用:它是一种用于实现线程同步的机制,确保了共享资源在多线程环境下的正确访问和修改,避免了数据不一致性和竞态条件等问题...
1. **synchronized的基本原理** `synchronized`关键字在Java中提供了互斥访问,也就是说,当一个线程进入一个对象的`synchronized`代码块或方法时,其他线程对这个对象的`synchronized`代码块或方法的访问将会被...
1. 同步方法: 当`synchronized`用作方法修饰符时,它会锁定调用该方法的对象。例如,如果在一个类中有两个不同的对象P1和P2,它们各自调用同一个同步方法,这两个线程会形成互斥,即在任何时刻只有一个线程能够...
1. `@synchronized`是基于对象的,传入的对象不能为`nil`,否则无效。 2. 由于使用了递归锁,它可以安全地在同步块内嵌套使用,不会引发死锁。 3. 性能相对较慢,不适用于需要高性能同步的场景。 4. 对象的生命周期...