public class MyClass extends Thread
{
static Object lock1 = new Object();
static Object lock2 = new Object();
static volatile int i1, i2, j1, j2, k1, k2;
public void run()
{
while(true)
{
doit();
check();
}
}
void doit()
{
synchronized(lock1)
{
i1++;
} synchronized(lock1)
{
i2++;
} synchronized(lock2)
{
k1++;
k2++;
}
j2++;
j1++;
}
void check()
{
if(i1 != i2)
{
System.out.println("i");
}
if(j1 != j2)
{
System.out.println("j");
}
if(k1 != k2)
{
System.out.println("k");
}
}
public static void main(String[] args)
{
new MyClass().start();
new MyClass().start();
}
}高手给解释下为什么打印的结果全是“i”啊?
谢谢了!
原因,main()为主线程不必多说 其他两个线程暂时成为一线程,二线程;
一线程启动调用doit()方法,执行i1++,此时,doit()方法中所用被synchronized的代码段
都将被一线程锁定;check()方法执行,打印“i”,因为j2++;j1++;并没有被锁,所以会执行;
在某个时间片 二线程启动调用doit()方法,若此时被锁代码未解锁,则执行j2++;j1++; 然而当
j2++执行,j1++未执行时被锁代码解锁,则另为一个线程也执行j2++,即j2++执行两次,而j1++执行
一次则j1 != j2 打印“j”;由于k1++;k2++;这段代码同在一个被锁代码段内,所以k1==k2;
最后 run()是死循环,自然线程不会停止,check()不会停止;
到此,我暂且了解这么多,不足处见谅!
j2++;j1++;它并非独占式的资源,应该也是要都执行,个人理解,不知道是不是这样!!
我再试试,刚才试了了好多遍,打印出来的全是"i"但是把doit()方法中语句位置调整一下就会打印出"i"和"j"比如说这样void doit()
{
synchronized(lock1)
{
i1++;
}
j2++;
synchronized(lock1)
{
i2++;
} synchronized(lock2)
{
k1++;
k2++;
}
j1++;
}
"i"和"j"就都会出现
j出现的可能性最大
其次是i
可能性最小的是k,
我改了下代码测试(实际上分别去掉那几个system.out.println也一样可以看出效果)
public class MyClass extends Thread
{
static Object lock1 = new Object();
static Object lock2 = new Object();
private static final ThreadLocal threadLocali = new ThreadLocal();
private static final ThreadLocal threadLocalj = new ThreadLocal();
private static final ThreadLocal threadLocalk = new ThreadLocal();
Boolean i=new Boolean(true);
Boolean j=new Boolean(true);
Boolean k=new Boolean(true);
static volatile int i1, i2, j1, j2, k1, k2;
public void run()
{
while(true)
{
doit();
check();
}
}
void doit()
{
synchronized(lock1)
{
i1++;
}
synchronized(lock1)
{
i2++;
} //Thread.sleep(5);
synchronized(lock2)
{
k1++;
k2++;
}
//Thread.sleep(5);
j2++;
j1++;
}
void check()
{
if (threadLocali.get()==null)
threadLocali.set(i);
if (threadLocalj.get()==null)
threadLocalj.set(j);
if (threadLocalk.get()==null)
threadLocalk.set(k);
if(i1 != i2)
{
Boolean i=(Boolean)threadLocali.get();
if (i.booleanValue()) {
System.out.println("i;"+i1+","+i2);
i=new Boolean(false);
threadLocali.set(i);
}
}
if(j1 != j2)
{
Boolean j=(Boolean)threadLocalj.get();
if (j.booleanValue()) {
System.out.println("j;"+j1+","+j2);
j=new Boolean(false);
threadLocalj.set(j);
}
}
if(k1 != k2)
{
Boolean k=(Boolean)threadLocalk.get();
if (k.booleanValue()) {
System.out.println("k;"+k1+","+k2);
k=new Boolean(false);
threadLocalk.set(k);
}
}
}
public static void main(String[] args)
{
new MyClass().start();
new MyClass().start();
}
}