synchronized 类锁&对象锁
synchronized 类锁
概述
synchronized 类锁是作用于静态方法或者某一个具体的类上的锁。
语法
- 作用于静态方法
synchronized public static void methodA() {
// code
}
- 作用于类
synchronized(Object.class) {
// code
}
synchronized 对象锁
概述
对象锁即作用于普通方法上(非静态)、类对象、this
关键字上的锁
语法
- 修饰普通方法
synchronized public void methodB() {
// code
}
- 修饰
this
关键字
synchronized(this) {
// code
}
synchronized 私有锁
概述
synchronized 私有锁即在类内部声明一个声明一个对象锁lock,在需要加锁的代码块中使用synchronized(obj)来加锁
语法
public class Test {
// 套餐的奇妙
private Object lock = new Object();
private int i = 0;
public void count(){
// 加锁
synchronized(lock){
i++;
}
}
}
示例程序
对象锁、类锁、私有锁应用类
public class LockTestClass {
// 用于类锁计数
private static int i = 0;
// 私有锁
private Object object = new Object();
/**
* 无锁方法
* @param threadID
* @param thread
*/
public void noSynMethod(long threadID, ObjThread thread) {
System.out.println("nosyn: class obj is:\t" + thread + "\t threadId:\t" + threadID);
}
/**
* 对象锁方法1
* synchronized 修饰非静态方法
*/
synchronized public void synOnMethod() {
System.out.println("对象锁方法1:\t synchronized public void method:" + "\t\t当前时间毫秒数:\t" + System.currentTimeMillis() + "ms");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("对象锁方法1:\t synchronized public void method 结束");
}
/**
* 对象锁方法2
* synchronized 修饰 this 当前类对象
*/
public void synInMethod() {
synchronized(this) {
System.out.println("对象锁方法2:\t synchronized(this):" + "\t\t当前时间毫秒数:\t" + System.currentTimeMillis() + "ms");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("对象锁方法2:\t synchronized(this)结束");
}
}
/**
* 私有锁
* synchronized(obj) 修饰对象
*/
public void synMethodWithObj() {
synchronized(object) {
System.out.println("私有锁:\t synchronized(obj):" + "\t\t当前时间毫秒数:\t" + System.currentTimeMillis() + "ms");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("私有锁:\t synchronized(obj)结束");
}
}
/**
* 类锁
*/
synchronized public static void increament() {
System.out.println("类锁: i = " + i + "\t\t当前时间毫秒数:\t" + System.currentTimeMillis() + "ms");
i++;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("类锁结束");
}
}
线程类
public class ObjThread extends Thread {
private LockTestClass lock;
private int i = 0;
public ObjThread(LockTestClass lock, int i) {
this.lock = lock;
this.i = i;
}
@Override
public void run() {
// // 无锁方法
// lock.noSynMethod(this.getId(), this);
// 对象锁方法1,synchronized 修饰非静态方法
lock.synOnMethod();
// 对象锁方法2, synchronized 修饰 this 当前类对象
lock.synInMethod();
私有锁方法,synchronized 修饰对象
// lock.synMethodWithObj();
// 类锁方法,synchronized修饰静态方法
// LockTestClass.increament();
}
}
注意:run()
方法中根据不同的需要去测试
测试类
public class Test {
public static void main(String[] args) {
System.out.println("start time = " + System.currentTimeMillis()+"ms");
LockTestClass test = new LockTestClass();
for (int i = 0 ; i < 3 ; i ++) {
Thread thread = new ObjThread(test, i);
thread.start();
}
}
}
测试结果
- 对象锁&类锁
run()
方法代码
@Override
public void run() {
// 无锁方法
// lock.noSynMethod(this.getId(), this);
// 对象锁方法1,synchronized 修饰非静态方法
lock.synOnMethod();
// 对象锁方法2, synchronized 修饰 this 当前类对象
// lock.synInMethod();
// 私有锁方法,synchronized 修饰对象
// lock.synMethodWithObj();
// 类锁方法,synchronized修饰静态方法
LockTestClass.increament();
}
终端输出:
start time = 1527579928236ms
对象锁方法1: synchronized public void method: 当前时间毫秒数: 1527579928238ms
对象锁方法1: synchronized public void method 结束
对象锁方法1: synchronized public void method: 当前时间毫秒数: 1527579930243ms
类锁: i = 0 当前时间毫秒数: 1527579930243ms
对象锁方法1: synchronized public void method 结束
类锁结束
对象锁方法1: synchronized public void method: 当前时间毫秒数: 1527579932248ms
类锁: i = 1 当前时间毫秒数: 1527579932248ms
类锁结束
对象锁方法1: synchronized public void method 结束
类锁: i = 2 当前时间毫秒数: 1527579934253ms
类锁结束
分析:当线程1启动时,优先执行了lock.synOnMethod();
对象锁方法1,且休眠2秒后,线程2启动,并再次执行lock.synOnMethod();
对象锁方法1,同时,类锁方法开始第一次执行(即线程1启动时)。说明类锁和对象锁之间不会产生竞争,互不影响。
- 对象锁&私有锁
run()
方法代码
@Override
public void run() {
// 无锁方法
// lock.noSynMethod(this.getId(), this);
// 对象锁方法1,synchronized 修饰非静态方法
lock.synOnMethod();
// 对象锁方法2, synchronized 修饰 this 当前类对象
// lock.synInMethod();
// 私有锁方法,synchronized 修饰对象
lock.synMethodWithObj();
// 类锁方法,synchronized修饰静态方法
// LockTestClass.increament();
}
终端输出:
start time = 1527581132501ms
对象锁方法1: synchronized public void method: 当前时间毫秒数: 1527581132504ms
对象锁方法1: synchronized public void method 结束
对象锁方法1: synchronized public void method: 当前时间毫秒数: 1527581134507ms
私有锁: synchronized(obj): 当前时间毫秒数: 1527581134507ms
对象锁方法1: synchronized public void method 结束
私有锁: synchronized(obj)结束
对象锁方法1: synchronized public void method: 当前时间毫秒数: 1527581136513ms
私有锁: synchronized(obj): 当前时间毫秒数: 1527581136513ms
对象锁方法1: synchronized public void method 结束
私有锁: synchronized(obj)结束
私有锁: synchronized(obj): 当前时间毫秒数: 1527581138516ms
私有锁: synchronized(obj)结束
分析:结果类似于对象锁&类锁。说明对象锁和私有锁之间也不会产生竞争、互不影响。
- 对象锁&私有锁
run()
方法代码
@Override
public void run() {
// 无锁方法
// lock.noSynMethod(this.getId(), this);
// 对象锁方法1,synchronized 修饰非静态方法
lock.synOnMethod();
// 对象锁方法2, synchronized 修饰 this 当前类对象
lock.synInMethod();
// 私有锁方法,synchronized 修饰对象
// lock.synMethodWithObj();
// 类锁方法,synchronized修饰静态方法
// LockTestClass.increament();
}
终端输出:
start time = 1527581386649ms
对象锁方法1: synchronized public void method: 当前时间毫秒数: 1527581386650ms
对象锁方法1: synchronized public void method 结束
对象锁方法1: synchronized public void method: 当前时间毫秒数: 1527581388655ms
对象锁方法1: synchronized public void method 结束
对象锁方法2: synchronized(this): 当前时间毫秒数: 1527581390657ms
对象锁方法2: synchronized(this)结束
对象锁方法1: synchronized public void method: 当前时间毫秒数: 1527581392659ms
对象锁方法1: synchronized public void method 结束
对象锁方法2: synchronized(this): 当前时间毫秒数: 1527581394663ms
对象锁方法2: synchronized(this)结束
对象锁方法2: synchronized(this): 当前时间毫秒数: 1527581396664ms
对象锁方法2: synchronized(this)结束
分析:两者结果串行输出,注意再次执行时,是lock.synOnMethod();
先运行还是lock.synInMethod();
先运行取决于两者谁先获取锁。
synchronized 类锁&对象锁&私有锁 比较结论
- 类锁&对象锁:多线程运行过程中,类锁与对象锁不产生锁竞争、各自运行、互不影响
- 对象锁&私有锁:多线程运行过程中,对象锁&私有锁不产生锁竞争、各自运行、互不影响
- 对象锁&对象锁:
synchronized(this)
和synchronized public void method()
都是在当前对象上加锁,且形成了锁竞争关系,同一时刻只能有一个方法能执行。
参考链接:
http://ifeve.com/java-locks/
https://blog.csdn.net/luoweifu/article/details/46613015这里写链接内容
https://blog.csdn.net/qyp199312/article/details/78438273
https://www.cnblogs.com/owenma/p/8609348.html