点击上方Java学习指南关注公众号
java
天天阅读Java干货文章web
synchronized 加到 static 方法前面是给class 加锁,即类锁;而synchronized 加到非静态方法前面是给对象上锁。面试
这二者的区别我用代码来演示下微信
对象锁和类锁是不一样的锁,因此多个线程同时执行这2个不一样锁的方法时,是异步的。
在Task2 中定义三个方法 doLongTimeTaskA和doLongTimeTaskB是类锁,而doLongTimeTaskC是对象锁。多线程
public class Task2 {
public synchronized static void doLongTimeTaskA() {
System.out.println("name = " + Thread.currentThread().getName() + ", begain");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("name = " + Thread.currentThread().getName() + ", end");
}
public synchronized static void doLongTimeTaskB() {
System.out.println("name = " + Thread.currentThread().getName() + ", begain");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("name = " + Thread.currentThread().getName() + ", end");
}
public synchronized void doLongTimeTaskC() {
System.out.println("name = " + Thread.currentThread().getName() + ", begain");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("name = " + Thread.currentThread().getName() + ", end");
}
三个线程的代码以下:app
class ThreadA extends Thread{
private Task2 mTask2;
public ThreadA(Task2 tk){
mTask2 = tk;
}
public void run() {
mTask2.doLongTimeTaskA();
}
}
class ThreadB extends Thread{
private Task2 mTask2;
public ThreadB(Task2 tk){
mTask2 = tk;
}
public void run() {
mTask2.doLongTimeTaskB();
}
}
class ThreadC extends Thread{
private Task2 mTask2;
public ThreadC(Task2 tk){
mTask2 = tk;
}
public void run() {
mTask2.doLongTimeTaskC();
}
}
main函数中执行代码以下:异步
Task2 mTask2 = new Task2();
ThreadA ta = new ThreadA(mTask2);
ThreadB tb = new ThreadB(mTask2);
ThreadC tc = new ThreadC(mTask2);
ta.setName("A");
tb.setName("B");
tc.setName("C");
ta.start();
tb.start();
tc.start();
执行的结果以下:编辑器
name = A, begain, time = 1487311199783
name = C, begain, time = 1487311199783
name = C, end, time = 1487311200784
name = A, end, time = 1487311200784
name = B, begain, time = 1487311200784
name = B, end, time = 1487311201784
能够看出因为 doLongTimeTaskA和doLongTimeTaskB都是类锁,即同一个锁,因此 A和B是按顺序执行,即同步的。而C是对象锁,和A/B不是同一种锁,因此C和A、B是 异步执行的。(A、B、C代指上面的3中方法)。函数
更多面试题,欢迎关注公众号 Java面试题精选学习
咱们知道对象锁要想保持同步执行,那么锁住的必须是同一个对象。下面就修改下上面的来证实:
Task2.java不变,修改ThreadA 和 ThreadB 以下:
class ThreadA extends Thread{
private Task2 mTask2;
public ThreadA(Task2 tk){
mTask2 = tk;
}
public void run() {
mTask2.doLongTimeTaskC();
}
}
class ThreadB extends Thread{
private Task2 mTask2;
public ThreadB(Task2 tk){
mTask2 = tk;
}
public void run() {
mTask2.doLongTimeTaskC();
}
}
main方法以下:
Task2 mTaska = new Task2();
Task2 mTaskb = new Task2();
ThreadA ta = new ThreadA(mTaska );
ThreadB tb = new ThreadB(mTaskb );
ta.setName("A");
tb.setName("B");
ta.start();
tb.start();
结果以下:
name = A, begain, time = 1487311905775
name = B, begain, time = 1487311905775
name = B, end, time = 1487311906775
name = A, end, time = 1487311906775
从结果看来,对象锁锁的对象不同,分别是mTaska , mTaskb,因此线程A和线程B调用 doLongTimeTaskC 是异步执行的。
可是,类锁能够对类的全部对象的实例起做用。只需修改ThradA 和 ThreadB,main 方法不作改变,修改以下:
class ThreadA extends Thread{
private Task2 mTask2;
public ThreadA(Task2 tk){
mTask2 = tk;
}
public void run() {
//mTask2.doLongTimeTaskC();
mTask2.doLongTimeTaskA();
}
}
class ThreadB extends Thread{
private Task2 mTask2;
public ThreadB(Task2 tk){
mTask2 = tk;
}
public void run() {
//mTask2.doLongTimeTaskC();
mTask2.doLongTimeTaskA();
}
}
结果以下:
name = A, begain, time = 1487312239674
name = A, end, time = 1487312240674
name = B, begain, time = 1487312240674
name = B, end, time = 1487312241674
能够看出 在线程A执行完doLongTimeTaskA方法后,线程B才会得到该类锁接着去执行doLongTimeTaskA。也就是说,类锁对全部的该类对象都能起做用。
Java学习指南:一个只分享Java干货的公众号。
总结:
-
若是多线程同时访问同一类的 类锁(synchronized 修饰的静态方法)以及对象锁(synchronized 修饰的非静态方法)这两个方法执行是异步的,缘由:类锁和对象锁是两种不一样的锁。 -
类锁对该类的全部对象都能起做用,而对象锁不能。
做者:小猪快跑22
blog.csdn.net/zhujiangtaotaise/article/details/55509939
若是文章对您有帮助,请您分享、点赞、在看,一波三连支持一下做者,很是感谢!
本文分享自微信公众号 - Java学习指南(gh_85b94beaede2)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。