本文共 2393 字,大约阅读时间需要 7 分钟。
说到锁机制,不得不提到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关键字修饰的方法,已经从对象级别上升到类级别了,所以,不论多少对象,都共有这个方法,所以才出现这种不论多少对象都会线程等待的现象。
转载地址:http://nrtvb.baihongyu.com/