当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
日前在网上见到一道Java笔试试题,如题所述。给出的答案如下:
答:不能,一个对象的一个synchronized方法只能由一个线程访问。
本人认为有些所答非所问。故写了两个demo进行测试。发现答案要分三种情况讨论。
情况一:
当一个线程进入一个对象的一个synchronized方法后,其它线程访问该对象的非同步方法。
public class TestSync
{
public synchronized void run1()
{
for (int i = 0; i < 1000; i++)
{
System.out.println("execute run1");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
public void run2()
{
for (int i = 0; i < 1000; i++)
{
System.out.println("execute run2");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
public class TestThread
{
public static void main(String[] args)
{
final TestSync testSync = new TestSync();
Thread thread1 = new Thread(new Runnable()
{
@Override
public void run()
{
testSync.run1();
}
});
Thread thread2 = new Thread(new Runnable()
{
@Override
public void run()
{
testSync.run2();
}
});
thread1.start();
thread2.start();
}
}
运行结果:
一个线程在访问一个对象的同步方法时,另一个线程可以同时访问这个对象的非同步方法。 |
情况二:
当一个线程进入一个对象的一个synchronized方法后,其它线程也访问该同步方法。
运行结果:
一个线程在访问一个对象的同步方法时,另一个线程不能同时访问这个同步方法。(代码略) |
情况三:
当一个线程进入一个对象的一个synchronized方法后,其它线程同时访问该对象的其他同步方法。
public class TestSync
{
public synchronized void run1()
{
for (int i = 0; i < 1000; i++)
{
System.out.println("execute run1");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
public synchronized void run2()
{
for (int i = 0; i < 1000; i++)
{
System.out.println("execute run2");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
public class TestThread
{
public static void main(String[] args)
{
final TestSync testSync = new TestSync();
Thread thread1 = new Thread(new Runnable()
{
@Override
public void run()
{
testSync.run1();
}
});
Thread thread2 = new Thread(new Runnable()
{
@Override
public void run()
{
testSync.run2();
}
});
thread1.start();
thread2.start();
}
}
运行结果:
前提条件:多个线程所持有的对象锁共享且唯一,如果每个线程所持有的对象锁不一样,那么该对象是锁不住的!