关于多线程的对象锁 synchronized 面试题 对象锁总结


线程t2调用doother方式是否需要线程t1释放对象myClass的对象锁之后才能执行;
答案:不需要,因为doother方法根本就没有使用关键字synchronized修饰,也就是说我们调用这个方法根本就不需要对象锁。
具体实现请看下面的代码。

仅仅对dosome加锁 doother不做任何处理

package sybchro;

public class O1 {
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        MyThread myThread1= new MyThread(myClass);
        MyThread myThread2=new MyThread(myClass);
        //线程myThread1和myThread2拥有的是同意Myclass引用;
        myThread1.setName("t1");
        myThread2.setName("t2");
        myThread1.start();
        try {
            Thread.sleep(1000);//此处的Thread指的是Main线程
            //此处休眠主要是为了让myThread1先执行。
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        myThread2.start();
    }
}
class MyThread extends Thread{
    MyClass myClass;

    public MyThread(MyClass myClass) {
        this.myClass = myClass;
    }

    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("t1")){
            this.myClass.dosome();
        }
        if(Thread.currentThread().getName().equals("t2")){
            this.myClass.doother();
        }
    }
}
class MyClass{
    public synchronized void dosome(){
        System.out.println("dobebin");
        try {
            Thread.sleep(1000*10);
            //此处睡眠主要是为了验证myThread2调用doother方法并不受到对象锁的影响;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("doover");

    }
    public void doother(){
        //myThread2调用doother方法之所以不会受到对象锁的影响是因为doother方法根本就没用使用关键字
        //synchronized修饰。
        System.out.println("dobebin");
        System.out.println("doover");
    }
}

dosome 和 doother方法同时加锁

package sybchro;

public class O1 {
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        MyThread myThread1= new MyThread(myClass);
        MyThread myThread2=new MyThread(myClass);
        //线程myThread1和myThread2拥有的是同意Myclass引用;
        myThread1.setName("t1");
        myThread2.setName("t2");
        myThread1.start();
        try {
            Thread.sleep(1000);//此处的Thread指的是Main线程
            //此处休眠主要是为了让myThread1先执行。
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        myThread2.start();
    }
}
class MyThread extends Thread{
    MyClass myClass;

    public MyThread(MyClass myClass) {
        this.myClass = myClass;
    }

    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("t1")){
            this.myClass.dosome();
        }
        if(Thread.currentThread().getName().equals("t2")){
            this.myClass.doother();
        }
    }
}
class MyClass{
    public synchronized void dosome(){
        System.out.println("dobebin");
        try {
            Thread.sleep(1000*10);
            //此处睡眠主要是为了验证myThread2调用doother方法并不受到对象锁的影响;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("doover");

    }
    public synchronized void doother(){
        //myThread2调用doother方法之所以不会受到对象锁的影响是因为doother方法根本就没用使用关键字
        //synchronized修饰。
        System.out.println("dobebin");
        System.out.println("doover");
    }
}

创建了两个对象一个线程拥有一个对象,此时线程之间不会再产生争夺对象锁的现象,也就是说线程与线程之间变成了异步编程,线程与线程之间不会再有任何的关系。一个线程也不会去等待另一个线程释放掉对象锁了。

package sybchro;

public class O1 {
    public static void main(String[] args) {
        MyClass myClass1 = new MyClass();
        MyClass myClass2 = new MyClass();
        MyThread myThread1= new MyThread(myClass1);//一个线程一个对象
        MyThread myThread2=new MyThread(myClass2);
        //线程myThread1和myThread2拥有的是同意Myclass引用;
        myThread1.setName("t1");
        myThread2.setName("t2");
        myThread1.start();
        try {
            Thread.sleep(1000);//此处的Thread指的是Main线程
            //此处休眠主要是为了让myThread1先执行。
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        myThread2.start();
    }
}
class MyThread extends Thread{
    MyClass myClass;

    public MyThread(MyClass myClass) {
        this.myClass = myClass;
    }

    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("t1")){
            this.myClass.dosome();
        }
        if(Thread.currentThread().getName().equals("t2")){
            this.myClass.doother();
        }
    }
}
class MyClass{
    public synchronized void dosome(){
        System.out.println("dobebin");
        try {
            Thread.sleep(1000*10);
            //此处睡眠主要是为了验证myThread2调用doother方法并不受到对象锁的影响;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("doover");

    }
    public synchronized void doother(){
        //myThread2调用doother方法之所以不会受到对象锁的影响是因为doother方法根本就没用使用关键字
        //synchronized修饰。
        System.out.println("dobebin");
        System.out.println("doover");
    }
}

总结:

我们加锁的目的主要是为了在对共享数据操作时保证数据的安全性问题,如果我们操作的不是共性的数据是不需要加锁的,加锁会使得程序的运行效率变慢(加锁也叫做同步编程不加锁叫做异步编程)

只有多个线程拥有一个共享的对象时,我们才能为这个对象加锁,只有拿到这个对象锁的人释放掉这个对象的对象锁其他的线程才有机会去争夺这个对象的对象锁。

只有拥有对象锁的线才可以使用这个共享的对象

synchronized(“这里放的就是那个共享的对象,不能为空,”)

一个对象只有一个对象锁,只有拥有这个对象锁的线程才可以使用这个对象去执行其他的功能。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值