synchronized可以锁对象,代码块,类对象 ,那么他们用起来会有区别吗,这里我们用实际代码来探究下
package com.example.hxk.thread.synchroized;
public class SyncTest1 {
// synchronized修饰非静态方法
public synchronized void test1() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// synchronized代码块
public void test2() {
synchronized (this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
SyncTest1 t1 = new SyncTest1();
new Thread(new Runnable() {
@Override
public void run() {
t1.test1();
}
}, "thread1").start();
new Thread(new Runnable() {
@Override
public void run() {
t1.test2();
}
}, "thread2").start();
}
}
运行结果:
thread1 : 0
thread1 : 1
thread1 : 2
thread1 : 3
thread1 : 4
thread2 : 0
thread2 : 1
thread2 : 2
thread2 : 3
thread2 : 4
这里thread2会等thread1运行完成才会开始运行,说明thread1和thread2请求的是同一把锁,也就说明了 synchronized代码块锁当前对象和锁非静态方法,他们的效果是一样的, 锁的都是当前对象。
然后我们再来看看类锁,修改代码如下
package com.example.hxk.thread.synchroized;
public class SyncTest1 {
// 修饰静态方法
public static synchronized void test1() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 修饰类对象
public void test2() {
synchronized (SyncTest1.class) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
SyncTest1 t1 = new SyncTest1();
new Thread(new Runnable() {
@Override
public void run() {
SyncTest1.test1();
}
}, "thread1").start();
new Thread(new Runnable() {
@Override
public void run() {
t1.test2();
}
}, "thread2").start();
}
}
运行结果:
thread1 : 0
thread1 : 1
thread1 : 2
thread1 : 3
thread1 : 4
thread2 : 0
thread2 : 1
thread2 : 2
thread2 : 3
thread2 : 4
这里可以看到thread2也是被thread1阻塞,所以他们持有的是同一把锁,也就说明synchronized修饰静态方法和锁类对象,他们的效果是一样的。 接下来我们同时用类锁和对象锁试试,代码如下
package com.example.hxk.thread.synchroized;
public class SyncTest1 {
// 修饰静态方法
public static synchronized void test1() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 修饰类对象
public synchronized void test2() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
SyncTest1 t1 = new SyncTest1();
new Thread(new Runnable() {
@Override
public void run() {
SyncTest1.test1();
}
}, "thread1").start();
new Thread(new Runnable() {
@Override
public void run() {
t1.test2();
}
}, "thread2").start();
}
}
运行结果:
thread1 : 0
thread2 : 0
thread1 : 1
thread2 : 1
thread2 : 2
thread1 : 2
thread2 : 3
thread1 : 3
thread2 : 4
thread1 : 4
运行结果是交替进行的,说明对象锁和类锁锁的不是同一个锁,他们是两个锁,互不影响
总结:
1,synchronized修饰在非静态方法上和synchronized(this){} 同步代码块效果是一样的
2,synchronized修饰在静态方法上和 synchronized (SyncTest1.class) {} 同步代码块效果是一样的
3,synchronized修饰在非静态方法表示锁的是当前对象,修饰静态方法表示锁的是类对象(一个类在jvm中只有一个class对象)