一、概述
- synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性。
- 多线程访问synchronized方法或代码块时,变成了单线程串行的方式。
二、基本认识
package com.cfl.thread;
public class Thread7 {
private final static Object MONITOR = new Object();
public static void main(String[] args) throws Exception {
Runnable runnable = new Runnable() {
public void run() {
try {
synchronized (MONITOR) {
System.out.println(Thread.currentThread().getName());
Thread.sleep(100*1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
Thread thread3 = new Thread(runnable);
thread1.start();
thread2.start();
thread3.start();
}
}
# 控制台打印
Thread-0
# jconsole查看线程
名称: Thread-0
状态: TIMED_WAITING
总阻止数: 0, 总等待数: 1
堆栈跟踪:
java.lang.Thread.sleep(Native Method)
com.cfl.thread.Thread7$1.run(Thread7.java:14)
- 已锁定 java.lang.Object@70866080
java.lang.Thread.run(Thread.java:748)
名称: Thread-1
状态: java.lang.Object@70866080上的BLOCKED, 拥有者: Thread-0
总阻止数: 1, 总等待数: 0
堆栈跟踪:
com.cfl.thread.Thread7$1.run(Thread7.java:13)
java.lang.Thread.run(Thread.java:748)
名称: Thread-2
状态: java.lang.Object@70866080上的BLOCKED, 拥有者: Thread-0
总阻止数: 1, 总等待数: 0
堆栈跟踪:
com.cfl.thread.Thread7$1.run(Thread7.java:13)
java.lang.Thread.run(Thread.java:748)
- 可以看到Thread-0在执行,状态:TIMED_WAITING。
- Thread-1和Thread-2已锁,状态:BLOCKED
二、同步代码块和方法
static class SynchronizedLock {
private final Object LOCK = new Object();
public void m1() {
System.out.println(Thread.currentThread().getName() + " start ");
synchronized (LOCK) {
try {
System.out.println(Thread.currentThread().getName() + " synchronized");
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void m2() {
try {
System.out.println(Thread.currentThread().getName() + " synchronized");
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void m3() {
try {
System.out.println(Thread.currentThread().getName() + " synchronized");
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1、同步代码块
public static void main(String[] args) throws Exception {
final SynchronizedLock lock = new SynchronizedLock();
Thread thread1 = new Thread(new Runnable() {
public void run() {
lock.m1();
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
lock.m1();
}
});
Thread thread3 = new Thread(new Runnable() {
public void run() {
lock.m1();
}
});
thread1.start();
thread2.start();
thread3.start();
}
Thread-2 start
Thread-0 start
Thread-1 start
Thread-2 synchronized
- m1方法是并行执行的,但是m1方法LOCK锁里面的代码块时串行执行的。
2、同步方法
public static void main(String[] args) throws Exception {
final SynchronizedLock lock = new SynchronizedLock();
Thread thread1 = new Thread(new Runnable() {
public void run() {
lock.m2();
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
lock.m2();
}
});
Thread thread3 = new Thread(new Runnable() {
public void run() {
lock.m3();
}
});
thread1.start();
thread2.start();
thread3.start();
}
Thread-0 synchronized
- 当synchronized同步方法时,该方法串行执行。
- synchronized同步方法时,实际上是this锁。
三、this锁
package com.cfl.thread;
public class Thread7 {
public static void main(String[] args) throws Exception {
final SynchronizedLock lock = new SynchronizedLock();
Thread thread1 = new Thread(new Runnable() {
public void run() {
lock.m1();
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
lock.m1();
}
});
Thread thread3 = new Thread(new Runnable() {
public void run() {
lock.m2();
}
});
Thread thread4 = new Thread(new Runnable() {
public void run() {
lock.m3();
}
});
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
static class SynchronizedLock {
public void m1() {
System.out.println(Thread.currentThread().getName() + " start");
synchronized (this) {
try {
System.out.println(Thread.currentThread().getName() + " synchronized");
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void m2() {
try {
System.out.println(Thread.currentThread().getName() + " synchronized");
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void m3() {
try {
System.out.println(Thread.currentThread().getName() + " synchronized");
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Thread-0 start
Thread-2 synchronized
Thread-1 start
- 当synchronized用this同步代码块的时候,代码块里面的内容和方法也是串行执行。
- 代码块外面的代码并行执行
4、this锁和对象锁并存
package com.cfl.thread;
public class Thread7 {
public static void main(String[] args) throws Exception {
final SynchronizedLock lock = new SynchronizedLock();
Thread thread1 = new Thread(new Runnable() {
public void run() {
lock.m1();
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
lock.m2();
}
});
Thread thread3 = new Thread(new Runnable() {
public void run() {
lock.m3();
}
});
thread1.start();
thread2.start();
thread3.start();
}
static class SynchronizedLock {
private final Object LOCK = new Object();
public void m1() {
System.out.println(Thread.currentThread().getName() + " start");
synchronized (LOCK) {
try {
System.out.println(Thread.currentThread().getName() + " synchronized");
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void m2() {
try {
System.out.println(Thread.currentThread().getName() + " synchronized");
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void m3() {
try {
System.out.println(Thread.currentThread().getName() + " synchronized");
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Thread-0 start
Thread-0 synchronized
Thread-1 synchronized
- this锁和对象锁互相独立,并行执行。
四、Class锁
package com.cfl.thread;
/**
* Synchronized class锁
* @author chenfenli
*
*/
public class Thread8 {
public static void main(String[] args) throws Exception {
Thread thread1 = new Thread(new Runnable() {
public void run() {
ClassLock.m1();
}
},"T1");
Thread thread2 = new Thread(new Runnable() {
public void run() {
ClassLock.m2();
}
},"T2");
Thread thread3 = new Thread(new Runnable() {
public void run() {
ClassLock.m3();
}
},"T3");
Thread thread4 = new Thread(new Runnable() {
public void run() {
ClassLock.m4();
}
},"T4");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
static class ClassLock {
static {
synchronized (ClassLock.class) {
System.out.println(Thread.currentThread().getName() + " 静态块 " + System.currentTimeMillis() + " synchronized");
try {
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized static void m1() {
System.out.println(Thread.currentThread().getName() + " " + System.currentTimeMillis() + " synchronized");
try {
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized static void m2() {
System.out.println(Thread.currentThread().getName() + " " + System.currentTimeMillis() + " synchronized");
try {
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized static void m3() {
System.out.println(Thread.currentThread().getName() + " " + System.currentTimeMillis() + " synchronized");
try {
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void m4() {
System.out.println(Thread.currentThread().getName() + " " + System.currentTimeMillis() + " synchronized");
}
}
}
T1 静态块 1563370479790 synchronized
T4 1563370489794 synchronized
T1 1563370489794 synchronized
T2 1563370499797 synchronized
T3 1563370509802 synchronized
- 可以看到静态块里面的锁在初始化对象的时候最先开始执行。
- 静态块里面的锁执行完成之后,锁被T1抢到,T1和不加锁的T4同时执行。
- T1执行完之后锁被T2抢到。
- T2执行完之后被T3抢到锁,执行完成。