Synchronized小记
对Synchronized一直理解的比较恍惚,抽时间查阅了一下资料,并且经过例子验证,放在这里记录一下。
基本用法应该都知道。先上测试代码:
public class SynchronizedTest {
private String lock = new String();
public void syncClass() {
synchronized (SynchronizedTest.class) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+ ": Sync class loop " + i);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void syncClassThis() {
synchronized (SynchronizedTest.this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+ ": Sync class.this loop " + i);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void syncThis() {
synchronized (this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+ ": Sync this loop " + i);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void syncGlobalVar() {
synchronized (lock) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+ ": Sync gloable variable loop " + i);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void syncLocalVar() {
String flag = new String();
synchronized (flag) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+ ": Sync local variable loop " + i);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public synchronized void syncMethod() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+ ": Sync method loop " + i);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static synchronized void syncStaticMethod() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+ ": Sync static method loop " + i);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Main函数代码如下:
public static void main(String[] args) {
final SynchronizedTest a = new SynchronizedTest();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
// a.syncClass();
// a.syncClassThis();
// a.syncThis();
// a.syncGlobalVar();
// a.syncLocalVar();
// a.syncMethod();
// a.syncStaticMethod();
}
});
t1.setName("A");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
// a.syncClass();
// a.syncClassThis();
// a.syncThis();
// a.syncGlobalVar();
// a.syncLocalVar();
// a.syncMethod();
// a.syncStaticMethod();
}
});
t2.setName("B");
t2.start();
}
Part A
A1. Synchronized(ClassName.class)和Synchronized(ClassName.class)
执行代码如下:
public static void main(String[] args) {
final SynchronizedTest a = new SynchronizedTest();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
a.syncClass();
}
});
t1.setName("A");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
a.syncClass();
}
});
t2.setName("B");
t2.start();
}
执行结果如下:
A: Sync class loop 0
A: Sync class loop 1
A: Sync class loop 2
A: Sync class loop 3
A: Sync class loop 4
B: Sync class loop 0
B: Sync class loop 1
B: Sync class loop 2
B: Sync class loop 3
B: Sync class loop 4
分析:Synchronized(ClassName.class)将类的对象上锁。Class锁对类的所有对象实例起作用,多线程同步执行。
A2. Synchronized(ClassName.class)与Synchronized静态方法
执行代码如下:
public static void main(String[] args) {
final SynchronizedTest a = new SynchronizedTest();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
a.syncClass();
}
});
t1.setName("A");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
a.syncStaticMethod();
}
});
t2.setName("B");
t2.start();
}
执行结果如下:
A: Sync class loop 0
A: Sync class loop 1
A: Sync class loop 2
A: Sync class loop 3
A: Sync class loop 4
B: Sync static method loop 0
B: Sync static method loop 1
B: Sync static method loop 2
B: Sync static method loop 3
B: Sync static method loop 4
分析:synchronized static方法与synchronized(ClassName.class)代码块的作用一样。线程同步执行。
A3. Synchronized(ClassName.class)与其他
这里其他指的是:
- a.syncClassThis() : synchronized (SynchronizedTest.this)
- a.syncThis() : synchronized (this)
- a.syncGlobalVar() : synchronized (lock) 全局变量lock
- a.syncLocalVar() : synchronized (flag) 本地变量flag
- a.syncMethod() : synchronized 非静态方法
其中一种执行结果:
A: Sync class loop 0
B: Sync method loop 0
B: Sync method loop 1
A: Sync class loop 1
A: Sync class loop 2
B: Sync method loop 2
B: Sync method loop 3
A: Sync class loop 3
A: Sync class loop 4
B: Sync method loop 4
我理解Synchronized(ClassName.class)与Synchronized静态方法是一个级别,对类的所有对象起作用,其他为一个级别。这两类别同用的时候,线程异步执行。
Part B
synchronized (ClassName.this)等同synchronized (this),在这里做一致处理。同步代码块,this是对用该方法的对象本身,而class是对该类本身。
B1. synchronized (this)与synchronized (this)
测试代码:
public static void main(String[] args) {
final SynchronizedTest a = new SynchronizedTest();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
a.syncThis();
}
});
t1.setName("A");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
a.syncThis();
}
});
t2.setName("B");
t2.start();
}
测试结果:
A: Sync this loop 0
A: Sync this loop 1
A: Sync this loop 2
A: Sync this loop 3
A: Sync this loop 4
B: Sync this loop 0
B: Sync this loop 1
B: Sync this loop 2
B: Sync this loop 3
B: Sync this loop 4
分析:当一个线程访问类的某个synchronized (this)同步代码块时,其它线程对同一个类中其它的synchronized (this)同步代码块的访问将是堵塞,这说明synchronized (this)使用的对象监视器是一个。
B2. synchronized (this)与synchronized 非静态方法
测试代码:
public static void main(String[] args) {
final SynchronizedTest a = new SynchronizedTest();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
a.syncThis();
}
});
t1.setName("A");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
a.syncMethod();
}
});
t2.setName("B");
t2.start();
}
测试结果:
A: Sync this loop 0
A: Sync this loop 1
A: Sync this loop 2
A: Sync this loop 3
A: Sync this loop 4
B: Sync method loop 0
B: Sync method loop 1
B: Sync method loop 2
B: Sync method loop 3
B: Sync method loop 4
分析:和B1一样,多个线程调用同一个对象中不同名称的synchronized同步非静态方法或者synchronized(this)同步代码块时,线程同步。
B3. synchronized (this)与synchronized 全局变量
测试代码:
public static void main(String[] args) {
final SynchronizedTest a = new SynchronizedTest();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
a.syncThis();
}
});
t1.setName("A");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
a.syncGlobalVar();
}
});
t2.setName("B");
t2.start();
}
结果(之一)如下:
A: Sync this loop 0
B: Sync gloable variable loop 0
A: Sync this loop 1
B: Sync gloable variable loop 1
A: Sync this loop 2
B: Sync gloable variable loop 2
B: Sync gloable variable loop 3
A: Sync this loop 3
A: Sync this loop 4
B: Sync gloable variable loop 4
this为调用syncThis()方法的对象实例,而syncGlobalVar()方法同步的是全局变量lock,互不影响,线程异步执行。
B4. synchronized (this)与synchronized 局部变量
测试代码:
public static void main(String[] args) {
final SynchronizedTest a = new SynchronizedTest();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
a.syncThis();
}
});
t1.setName("A");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
a.syncLocalVar();
}
});
t2.setName("B");
t2.start();
}
结果(之一)如下:
A: Sync this loop 0
B: Sync local variable loop 0
B: Sync local variable loop 1
A: Sync this loop 1
B: Sync local variable loop 2
A: Sync this loop 2
A: Sync this loop 3
B: Sync local variable loop 3
B: Sync local variable loop 4
A: Sync this loop 4
与B3一样,同步代码块分别锁定this实例和局部变量flag,互不干涉,线程异步。
B5. synchronized (this)与synchronized 静态方法
两个线程分别调用syncThis()方法和syncStaticMethod()方法。结果(之一)如下:
A: Sync this loop 0
B: Sync static method loop 0
A: Sync this loop 1
B: Sync static method loop 1
B: Sync static method loop 2
A: Sync this loop 2
A: Sync this loop 3
B: Sync static method loop 3
B: Sync static method loop 4
A: Sync this loop 4
分析:在A2中讲过,synchronized (ClassName.class)和synchronized 静态方法效果一样,属于同步类本身。互不影响,线程异步执行。
Part C
C1. Synchronized 全局变量和Synchronized 全局变量
测试代码:
public static void main(String[] args) {
final SynchronizedTest a = new SynchronizedTest();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
a.syncGlobalVar();
}
});
t1.setName("A");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
a.syncGlobalVar();
}
});
t2.setName("B");
t2.start();
}
测试结果:
A: Sync gloable variable loop 0
A: Sync gloable variable loop 1
A: Sync gloable variable loop 2
A: Sync gloable variable loop 3
A: Sync gloable variable loop 4
B: Sync gloable variable loop 0
B: Sync gloable variable loop 1
B: Sync gloable variable loop 2
B: Sync gloable variable loop 3
B: Sync gloable variable loop 4
分析:多个线程持有对象监视器作为同一个对象的前提下,同一时间只有一个线程可以执行synchronized(任意自定义对象)同步代码快。
C2. Synchronized 全局变量和Synchronized 局部变量
测试代码:
public static void main(String[] args) {
final SynchronizedTest a = new SynchronizedTest();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
a.syncGlobalVar();
}
});
t1.setName("A");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
a.syncLocalVar();
}
});
t2.setName("B");
t2.start();
}
测试结果(之一):
A: Sync gloable variable loop 0
A: Sync gloable variable loop 1
B: Sync local variable loop 0
A: Sync gloable variable loop 2
A: Sync gloable variable loop 3
B: Sync local variable loop 1
A: Sync gloable variable loop 4
B: Sync local variable loop 2
B: Sync local variable loop 3
B: Sync local variable loop 4
两个线程同步的为不同变量,线程异步执行。
C3. Synchronized 全局变量和Synchronized 非静态方法
测试代码:
public static void main(String[] args) {
final SynchronizedTest a = new SynchronizedTest();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
a.syncGlobalVar();
}
});
t1.setName("A");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
a.syncMethod();
}
});
t2.setName("B");
t2.start();
}
测试结果(之一):
A: Sync gloable variable loop 0
B: Sync method loop 0
A: Sync gloable variable loop 1
B: Sync method loop 1
B: Sync method loop 2
A: Sync gloable variable loop 2
B: Sync method loop 3
A: Sync gloable variable loop 3
B: Sync method loop 4
A: Sync gloable variable loop 4
同步代码块对象为全局变量,另一方为调用同步非静态类方法的对象,互不干涉,线程异步执行。
Part D
D1. Synchronized 局部变量和Synchronized 局部变量
测试代码:
public static void main(String[] args) {
final SynchronizedTest a = new SynchronizedTest();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
a.syncLocalVar();
}
});
t1.setName("A");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
a.syncLocalVar();
}
});
t2.setName("B");
t2.start();
}
测试结果(之一):
A: Sync local variable loop 0
B: Sync local variable loop 0
B: Sync local variable loop 1
A: Sync local variable loop 1
A: Sync local variable loop 2
B: Sync local variable loop 2
A: Sync local variable loop 3
B: Sync local variable loop 3
B: Sync local variable loop 4
A: Sync local variable loop 4
这个结果显而易见,线程异步。事实上,Synchronized 局部变量与其他任何同步方法或者同步代码块执行的时候,因为上锁的“对象”不同,线程之间都是异步执行的。
总结
Synchronized可以同步代码块和同步方法,同一个实例在进行多线程调用的时候,线程之间的执行结果如下表:
执行结果 | synchronized (ClassName.class) | synchronized 静态方法 | synchronized (ClassName.this) | synchronized (this) | synchronized 非静态方法 | synchronized (全局变量) | synchronized (局部变量) |
synchronized (ClassName.class) | 同步 | 同步 | 异步 | 异步 | 异步 | 异步 | 异步 |
synchronized 静态方法 | 同步 | 同步 | 异步 | 异步 | 异步 | 异步 | 异步 |
synchronized (ClassName.this) | 异步 | 异步 | 同步 | 同步 | 同步 | 异步 | 异步 |
synchronized (this) | 异步 | 异步 | 同步 | 同步 | 同步 | 异步 | 异步 |
synchronized 非静态方法 | 异步 | 异步 | 同步 | 同步 | 同步 | 异步 | 异步 |
synchronized (全局变量) | 异步 | 异步 | 异步 | 异步 | 异步 | 同步 | 异步 |
synchronized (局部变量) | 异步 | 异步 | 异步 | 异步 | 异步 | 异步 | 异步 |