版权声明:欢迎转载,请注明作者和出处 https://blog.csdn.net/baichoufei90/article/details/83281014
Java学习-锁-synchronized之对象锁和类锁
0x01 摘要
synchronized是java中最常用的一种锁机制,本篇文章主要介绍他的两种用途:类锁和对象锁。
0x02 对象锁
synchronized
作为对象锁时,用在非静态方法或非静态对象上,下面是示例:
/**
* 对象锁
*/
public synchronized void nonStaticMethodLock(){
for(int i = 0 ; i< 5 ; i++){
System.out.println(Thread.currentThread().getName()+" nonStaticMethodLock");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 对象锁
*/
public void objectLock(){
synchronized(this){
for(int i = 0 ; i< 5 ; i++){
System.out.println(Thread.currentThread().getName()+" objectLock");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
0x03 类锁
类锁修饰方法、代码块的效果和对象锁是一样的,因为类锁只是一个抽象出来的概念,只是为了区别静态方法的特点。因为静态方法是所有对象实例共用的,所以对应synchronized修饰的静态方法的锁也是唯一的,所以抽象出来个类锁。
下面是代码示例:
/**
* 类锁
*/
public void classLock(){
synchronized(Test3.class){
for(int i = 0 ; i< 5 ; i++){
System.out.println(Thread.currentThread().getName()+" classLock");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 类锁
*/
public static synchronized void staticMethodLock(){
for(int i = 0 ; i< 5 ; i++){
System.out.println(Thread.currentThread().getName()+" staticMethodLock");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
0x04 代码示例
下面是完整的代码示例,可以自行调试观察结果,加深理解:
package demos.concurrent.thread.synchronizedTest.objectAndMethodLock;
/**
* Created by chengc on 2018/10/22.
*/
public class Test3 {
private Object nonStaticLockObj = new Object();
private static Object staticLockObj = new Object();
private static Object staticLockObj2 = new Object();
/**
* 类锁
*/
public void classLock(){
synchronized(Test3.class){
for(int i = 0 ; i< 5 ; i++){
System.out.println(Thread.currentThread().getName()+" classLock");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 类锁
*/
public static synchronized void staticMethodLock(){
for(int i = 0 ; i< 5 ; i++){
System.out.println(Thread.currentThread().getName()+" staticMethodLock");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void ordinaryMethod(){
for(int i = 0 ; i< 5 ; i++){
System.out.println(Thread.currentThread().getName()+" ordinaryMethod");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 对象锁
*/
public synchronized void nonStaticMethodLock(){
for(int i = 0 ; i< 5 ; i++){
System.out.println(Thread.currentThread().getName()+" nonStaticMethodLock");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 对象锁
*/
public void thisObjectLock(){
synchronized(this){
for(int i = 0 ; i< 5 ; i++){
System.out.println(Thread.currentThread().getName()+" thisObjectLock");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 对象锁
*/
public void nonStaticObjectLock(){
synchronized(nonStaticLockObj){
for(int i = 0 ; i< 5 ; i++){
System.out.println(Thread.currentThread().getName()+" nonStaticLockObj");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 对象锁
*/
public void staticObjectLock(){
synchronized(staticLockObj){
for(int i = 0 ; i< 5 ; i++){
System.out.println(Thread.currentThread().getName()+" staticLockObj");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 对象锁
*/
public void staticObjectLock2(){
synchronized(staticLockObj2){
for(int i = 0 ; i< 5 ; i++){
System.out.println(Thread.currentThread().getName()+" staticLockObj2");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Test3 test1 = new Test3();
new Thread(new Runnable() {
@Override
public void run() {
test1.classLock();
}
},"Thread1").start();
new Thread(new Runnable() {
@Override
public void run() {
test1.nonStaticMethodLock();
}
},"Thread2").start();
new Thread(new Runnable() {
@Override
public void run() {
test1.ordinaryMethod();
}
},"Thread3").start();
new Thread(new Runnable() {
@Override
public void run() {
test1.staticMethodLock();
}
},"Thread4").start();
new Thread(new Runnable() {
@Override
public void run() {
test1.thisObjectLock();
}
},"Thread5").start();
new Thread(new Runnable() {
@Override
public void run() {
test1.nonStaticObjectLock();
}
},"Thread6").start();
new Thread(new Runnable() {
@Override
public void run() {
test1.staticObjectLock();
}
},"Thread7").start();
new Thread(new Runnable() {
@Override
public void run() {
test1.staticObjectLock2();
}
},"Thread8").start();
}
}
0x05 总结
通过以上代码调试,总结如下:
- 写在方法上的synchronized锁和写在代码块上用
this
修饰的对象锁同时只能有一个线程进入执行,但不影响其他方法执行 - 写在静态方法和代码块上用
XXX.class
修饰的为类锁,同时只能有一个线程进入执行,但不影响其他方法执行 - 用其他自己声明的对象作为对象锁修饰的方法或是代码块,互不影响
- 普通方法不受对象锁和类锁影响