java中的类锁和对象锁对比分析

      说到锁机制,不得不提到Thread线程,而又不得不提到synchronized关键字,这个单词的意思是表示“同步”的意思。用它去修饰方法函数的时候,如果有多个线程同时调用这个方法函数的时候,那么当一个线程获得锁的时候,其他的线程只能进入等待队列,直到这根线程执行完毕,释放锁的时候,其他线程才可以获得锁去执行这个方法函数。

       这里我们主要讲的是对象锁和类锁。对象锁,顾名思义,即为对象级别的锁,一个对象一个锁,不论为这个对象创建多少个线程。类锁,同样的意思,即为类级别的锁,一个类一个锁,这个类的所有对象共有一个锁。这两个锁在形式上的区别是类锁会有一个static关键字修饰。

       下面来看看具体的例子,先定义一个具有对象锁和类锁的Demo类:

package com.Jevin.thread;

public class Demo {

    //对象锁:
    public synchronized void test01(){
        try {
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //类锁:
    public static synchronized void test02(){
        try {
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

      我们先创建一个对象两个线程去调用对象锁,观察一下执行情况:

package com.Jevin.thread;

public class ObjectLock {
    public static void main(String[] args){

        //定义一个对象:
        Demo d=new Demo();

        //创建线程对象:
        Thread t1=new Thread(new Runnable() {
            @Override
            public void run() {
                d.test01();
            }
        },"t1");
        Thread t2=new Thread(new Runnable() {
            @Override
            public void run() {
                d.test01();
            }
        },"t2");

        //启动线程:
        t1.start();
        t2.start();
    }
}

        执行情况:线程t1先执行,过了3秒钟后,线程t2再开始执行。那为什么呢?我的看法是:我们只创建了一个Demo对象,这个在堆中的对象包含了我们的对象锁的test01方法,两个线程进入同步块中,符合线程的执行规律。

         那么,我们创建两个对象,会发生什么现象呢?如下所示:

package com.Jevin.thread;

public class ObjectLock {
    public static void main(String[] args){

        //定义一个对象:
        Demo d1=new Demo();
        Demo d2=new Demo();

        //创建线程对象:
        Thread t1=new Thread(new Runnable() {
            @Override
            public void run() {
                d1.test01();
            }
        },"t1");
        Thread t2=new Thread(new Runnable() {
            @Override
            public void run() {
                d2.test01();
            }
        },"t2");

        //启动线程:
        t1.start();
        t2.start();
    }
}

       执行结果是:t1线程和t2线程同时执行,我的看法是:我们创建了两个对象,这两个对象各拥有自己的test01方法函数,线程t1中的t1引用调用自己堆中的对象的test01方法,线程t2中的引用t2调用自己堆中的test01方法,各自互不影响,所以不会出现线程等待那种情况。

      那么,问题来了,我去调用有static关键字修饰的test02方法,会怎样呢?答案是,不论一个对象,还是两个对象,或是n个对象,都会出先线程等待,线程一个一个的调用,为什么呢?我觉得:有static关键字修饰的方法,已经从对象级别上升到类级别了,所以,不论多少对象,都共有这个方法,所以才出现这种不论多少对象都会线程等待的现象。

猜你喜欢

转载自blog.csdn.net/boy_chen93/article/details/81207386