synchronized锁的介绍
synchronized锁的使用
synchronized可以使用在方法和代码块中, 使用的方式不同锁代表的含义不同, 下面将从几个方面进行介绍.
- 普通方法
- 静态方法
- 代码块synchronized(this)
- 代码块synchronized(*.class)
结论
- 在使用synchronized关键字中锁主要分为两类, 一种是对象锁, 另一种类锁
- 普通加锁方法和synchronized(this)都是对象锁, 静态加锁方法和synchronized(*.class)都是类锁
- 对象锁: 同一对象持有锁, 相同对象等待, 其他对象不受影响; 不同对象持有锁, 互不影响.
- 类锁: 类锁时, 只要该类的对象持有锁, 无论是否为同一对象访问静态同步方法时都等待, 访问非静态同步方法不受影响.
- 对象锁和类锁互相不影响
测试代码及过程
package com.liuzhihang.tool.sync;
/**
* @author liuzhihang
* @date 2018/7/11 16:25
*/
public class SyncMainTest {
public static void main(String[] args) {
SyncTest syncTest1 = new SyncTest();
// SyncTest syncTest2 = new SyncTest();
new Thread(() -> syncTest1.methodA(), "线程 01 ").start();
new Thread(() -> syncTest1.methodB(), "线程 02 ").start();
}
}
class SyncTest {
void methodA() {
System.out.println(Thread.currentThread().getName() + "start");
try {
System.out.println(Thread.currentThread().getName() + "sleep");
Thread.sleep(500);
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName() + "end");
}
void methodB() {
System.out.println(Thread.currentThread().getName() + "start");
try {
System.out.println(Thread.currentThread().getName() + "sleep");
Thread.sleep(300);
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName() + "end");
}
}
以上为一个简单的测试代码, 指使用两个线程分别调用两个方法, 通过打印结果可以看出顺序是乱序的, 其中线程的 start() 顺序并不代表线程的执行顺序, 在下面测试中假设是 "线程01" 先执行.
1.A B 方法分别添加synchronized关键字 + 同一对象
class SyncTest {
synchronized void methodA() {
// ...
}
synchronized void methodB() {
// ...
}
}
结论: 方法 A 阻塞, 方法 B 等待 A 执行完毕后才继续执行.
2.A B 方法分别添加synchronized关键字 + 不同对象
public class SyncMainTest {
public static void main(String[] args) {
SyncTest syncTest1 = new SyncTest();
SyncTest syncTest2 = new SyncTest();
new Thread(() -> syncTest1.methodA(), "线程 01 ").start();
new Thread(() -> syncTest2.methodB(), "线程 02 ").start();
}
}
class SyncTest {
synchronized void methodA() {
// ...
}
synchronized void methodB() {
// ...
}
}
结论: 方法 A 阻塞, 方法 B 不受影响.
3.A 方法分别添加synchronized关键字 B方法不添加
class SyncTest {
synchronized void methodA() {
// ...
}
void methodB() {
// ...
}
}
结论: 方法 A 阻塞, 方法 B 不受影响.
4.A B 方法分别添加 static synchronized + 不同对象
public class SyncMainTest {
public static void main(String[] args) {
SyncTest syncTest1 = new SyncTest();
SyncTest syncTest2 = new SyncTest();
new Thread(() -> syncTest1.methodA(), "线程 01 ").start();
new Thread(() -> syncTest2.methodB(), "线程 02 ").start();
}
}
class SyncTest {
static synchronized void methodA() {
// ...
}
static synchronized void methodB() {
// ...
}
}
结论: 方法 A 阻塞, 方法 B 等待 A结束后继续执行.
5.A 方法添加 static synchronized, B 方法添加 synchronized + 不同对象
public class SyncMainTest {
public static void main(String[] args) {
SyncTest syncTest1 = new SyncTest();
SyncTest syncTest2 = new SyncTest();
new Thread(() -> syncTest1.methodA(), "线程 01 ").start();
new Thread(() -> syncTest2.methodB(), "线程 02 ").start();
}
}
class SyncTest {
static synchronized void methodA() {
// ...
}
synchronized void methodB() {
// ...
}
}
结论: 方法 A 阻塞, 方法 B 不受影响.
6.A B 方法内添加 synchronized(this)
class SyncTest {
void methodA() {
synchronized (this) {
// ...
}
}
void methodB() {
synchronized (this) {
// ...
}
}
}
结论: 同一对象 A 阻塞 B等待, 不同对象 A阻塞 B不受影响
7.A B 方法内添加 synchronized(SyncTest.class)
class SyncTest {
void methodA() {
synchronized (SyncTest.class) {
// ...
}
}
void methodB() {
synchronized (SyncTest.class) {
// ...
}
}
}
结论: 同一/不同对象 A 阻塞 B等待
8.A 方法内添加 synchronized(SyncTest.class), B 方法内添加 synchronized(this)
class SyncTest {
void methodA() {
synchronized (SyncTest.class) {
// ...
}
}
void methodB() {
synchronized (this) {
// ...
}
}
}
结论: 同一/不同对象 A 阻塞 B不受影响
9.A 方法内添加 synchronized(SyncTest.class), B 方法内添加 synchronized(OtherObj)
class SyncTest {
private String string = "lock";
void methodA() {
synchronized (SyncTest.class) {
// ...
}
}
void methodB() {
synchronized (string) {
// ...
}
}
}
结论: 同一/不同对象 A 阻塞 B不受影响
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏