java 类锁 对象锁,Java中 synchronized 对象锁和类锁的区别

synchronized 加到 static 方法前面是给class 加锁,即类锁;而synchronized 加到非静态方法前面是给对象上锁。

Java中 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");

}

三个线程的代码如下:

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。也就是说,类锁对所有的该类对象都能起作用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值