上码:
package com.hxsmart.thread.synchronize; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.TimeUnit; public class CleanRoom { private Integer student=0; private Integer machine=0; public String getDateStr(){ return " Thread"+Thread.currentThread().getName()+" *time: "+new SimpleDateFormat("mm:ss").format(new Date()); } public void stuClean(){ System.out.println("enter stuClean"); synchronized (student) { for(int i=0;i<5;i++){ System.out.println("stu"+getDateStr()); student++; try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } } } } public void macClean(){ System.out.println("enter macClean"); synchronized (machine) { for(int i=0;i<5;i++){ System.out.println("mac"+getDateStr()); machine++; // try { // TimeUnit.SECONDS.sleep(3); // } catch (InterruptedException e) { // e.printStackTrace(); // } } } } public static void main(String[] args) { CleanRoom c=new CleanRoom(); StuThread t1=new StuThread(c); MacThread t2=new MacThread(c); t1.start(); t2.start(); } public Integer getStudent() { return student; } public void setStudent(Integer student) { this.student = student; } public Integer getMachine() { return machine; } public void setMachine(Integer machine) { this.machine = machine; } } class StuThread extends Thread{ CleanRoom clean; public StuThread() { super(); } public StuThread(CleanRoom clean) { super(); this.clean = clean; } @Override public void run() { //for(int i=0;i<5;i++) clean.stuClean(); System.out.println("stu: "+clean.getStudent()+"** mac:**"+clean.getMachine()); } public CleanRoom getClean() { return clean; } public void setClean(CleanRoom clean) { this.clean = clean; } } class MacThread extends Thread{ CleanRoom clean; public MacThread() { super(); } public MacThread(CleanRoom clean) { super(); this.clean = clean; } @Override public void run() { //for(int i=0;i<5;i++) clean.macClean(); System.out.println("stu: "+clean.getStudent()+"** mac:**"+clean.getMachine()); } public CleanRoom getClean() { return clean; } public void setClean(CleanRoom clean) { this.clean = clean; } }
输出:
enter stuClean enter macClean stu ThreadThread-0 *time: 12:38 stu ThreadThread-0 *time: 12:41 stu ThreadThread-0 *time: 12:44 stu ThreadThread-0 *time: 12:47 stu ThreadThread-0 *time: 12:50 stu: 5** mac:**0 mac ThreadThread-1 *time: 12:53 mac ThreadThread-1 *time: 12:53 mac ThreadThread-1 *time: 12:53 mac ThreadThread-1 *time: 12:53 mac ThreadThread-1 *time: 12:53 stu: 5** mac:**5
问题:
t1和t2线程,分别调用的是CleanRoom类同一实例c的不同方法,并且这两个方法没有把这个实例C锁上,两个方法所锁定的资源分别是c实例的两个不同的属性,按道理来说,这两个线程应该是并发执行的。
但是事实不如此,t2线程在t1线程没有执行完成前,始终处于等待状态。
求解!
当stuClean方法中调用TimeUnit.SECONDS.sleep(3)后,macClean()方法应该有机会得到执行啊?
哈哈,神秘现象不神秘。Integer类会缓存一部分对象,从-128到127的数在系统中都只有一个Integer对象(假如你用自动装箱和valueof方法得到对象,其实这两者是一回事)。因此你锁住的两个对象其实都是同一个Integer(0),当自增之后,那两个对象的引用指向了别的对象,比如Integer(1)。最终执行的结果就是student和machine都指向了Integer(5)。你把两个=0改成=new Integer(0)就OK啦。
你把private Integer student=0改成private Integer student=new Integer(0);同样private Integer machine=0;改成private Integer machine=new Integer(0);再试试看,应该就不会锁住了。
真的太神奇了。
难道是因为private Integer student=0和private Integer machine=0;实际上指向的是一个对象,所以锁被加在一个对象上,所以出现了等待的情况?
但是如果指向同一对象的话,machine不应该还是从0开始计数啊。
求哪位大神解释!
sleep执行的时候是没有释放锁的,他还手里面握着锁头的,其他线程竞争不走CPU资源的,他还占据着呢,
比如wait的话,在wait(3000),的时候这个时候系统的其他线是可以竞争CPU资源的。
本人的一点点见解