synchronized面试题
- 分析以下四个程序:判断t2线程是否需要等待t1线程执行完毕再执行?
(1)
package com.dh.threadsafe3;
public class SynchronizedTest {
public static void main(String[] args) {
Do d = new Do();
Thread t1 = new MyThread(d);
Thread t2 = new MyThread(d);
t1.setName("t1");
t2.setName("t2");
t1.start();
try {
Thread.sleep(1000); //保证t1线程先执行
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
}
}
class MyThread extends Thread {
private Do d;
public MyThread(Do d) {
this.d = d;
}
@Override
public void run() {
if(Thread.currentThread().getName().equals("t1")){
d.doSome();
}
if(Thread.currentThread().getName().equals("t2")){
d.doOther();
}
}
}
class Do{
//锁的是this对象
public synchronized void doSome(){
System.out.println("doSome begin");
try {
Thread.sleep(1000*5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("doSome over");
}
public void doOther(){
System.out.println("doOther begin");
System.out.println("doOther over");
}
}
此时t2线程是否需要等待t1线程先执行完毕?
不需要,虽然线程t1和线程t2共享this,但是因为t2线程不需要共享资源的锁,所以不需要等待t1线程执行完毕归还锁。
结果:
doSome begin
doOther begin
doOther over
doSome over
所以doOther()会先执行完毕。
(2)
(其余代码不变)
public synchronized void doOther(){
System.out.println("doOther begin");
System.out.println("doOther over");
}
此时因为t1线程和t2线程需要的是同一把对象的锁(this,即d),所以t2线程需要等先拿到锁的t1线程执行完毕归还锁之后,再拿到锁后执行代码。
结果:
doSome begin
doSome over
doOther begin
doOther over
(3)
package com.dh.threadsafe3;
public class SynchronizedTest {
public static void main(String[] args) {
Do d = new Do();
Thread t1 = new MyThread(d);
Do d2 = new Do();
Thread t2 = new MyThread(d2);
t1.setName("t1");
t2.setName("t2");
t1.start();
try {
Thread.sleep(1000); //保证t1线程先执行
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
}
}
class MyThread extends Thread {
private Do d;
public MyThread(Do d) {
this.d = d;
}
@Override
public void run() {
if(Thread.currentThread().getName().equals("t1")){
d.doSome();
}
if(Thread.currentThread().getName().equals("t2")){
d.doOther();
}
}
}
class Do{
public synchronized void doSome(){
System.out.println("doSome begin");
try {
Thread.sleep(1000*5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("doSome over");
}
public synchronized void doOther(){
System.out.println("doOther begin");
System.out.println("doOther over");
}
}
因为此时的this对象不一样了,t1线程的this是d,而t2线程的this是d2,所以等待的不是同一把锁,t2线程也不需要等待t1线程。
结果:
doSome begin
doOther begin
doOther over
doSome over
(4)
package com.dh.threadsafe3;
public class SynchronizedTest {
public static void main(String[] args) {
Do d = new Do();
Thread t1 = new MyThread(d);
Do d2 = new Do();
Thread t2 = new MyThread(d2);
t1.setName("t1");
t2.setName("t2");
t1.start();
try {
Thread.sleep(1000); //保证t1线程先执行
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
}
}
class MyThread extends Thread {
private Do d;
public MyThread(Do d) {
this.d = d;
}
@Override
public void run() {
if(Thread.currentThread().getName().equals("t1")){
d.doSome();
}
if(Thread.currentThread().getName().equals("t2")){
d.doOther();
}
}
}
class Do{
public synchronized static void doSome(){
System.out.println("doSome begin");
try {
Thread.sleep(1000*5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("doSome over");
}
public synchronized static void doOther(){
System.out.println("doOther begin");
System.out.println("doOther over");
}
}
synchronized修饰的是静态方法,所以需要找类锁,虽然是不同的this对象,但是是同一个类Do,所以是线程t1和t2需要的是同一把锁,所以t2线程需要等待t1线程。
结果:
doSome begin
doSome over
doOther begin
doOther over