扩展 Thread class 时无法同步两个线程,但在实现 Runnable 接口时可以工作
Unable to synchronize two threads when Thread class is extended but works when implementing Runnable interface
此处同步块不起作用:
class NewThreadt extends Thread {
synchronized void dota(){
for(int i = 5; i > 0; i--)
{
System.out.println(i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
}
}
// This is the entry point for the second thread.
public void run() {
dota() ;
System.out.println("Exiting child thread.");
System.out.println(Thread.currentThread()); //gives the name of thread
}
}
class trial {
public static void main(String args[]) {
NewThreadt t=new NewThreadt();
NewThreadt q=new NewThreadt();
t.start();
q.start(); both are in main
System.out.println("Main thread exiting.");
}
}
输出:
Main thread exiting.
5
5
4
4
3
3
2
2
1
1
但是当我进行以下更改时,同步块起作用:
class NewThreadt implements Runnable //instead of class NewThreadt extends Thread
NewThreadt abc=new NewThreadt(); //Changes in main()
Thread t=new Thread(abc);
Thread q=new Thread(abc);
t.start();
q.start();
输出:
Main thread exiting.
5
4
3
2
1
5
4
3
2
1
为什么会这样?这两个例子不是应该一样工作吗?
同步依赖于共享一个公用锁。实例方法上的 synchronized
关键字意味着要使线程进入该方法,它首先必须获取 this
.
上的锁
在你的第一个例子中没有共享锁,两个线程中的每一个都在锁定自己。每个线程获取自己的锁并且没有人阻塞,两个线程 运行 并发。 (这里唯一的锁定是,当一个线程想要写入控制台时,它必须首先获取控制台的锁,以便每个 println 以原子方式发生。)
在第二个示例中,相同的 Runnable 被传递到每个线程,因此它们都锁定在同一个对象上,即 Runnable。一个线程获取锁并执行,另一个必须等待第一个线程释放锁。
如果你改变第二个例子给每个线程一个单独的Runnable:
Thread t=new Thread(new NewThreadt());
Thread q=new Thread(new NewThreadt());
t.start();
q.start();
然后您会看到同步不起作用,它的行为与第一个示例相同。
此处同步块不起作用:
class NewThreadt extends Thread {
synchronized void dota(){
for(int i = 5; i > 0; i--)
{
System.out.println(i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
}
}
// This is the entry point for the second thread.
public void run() {
dota() ;
System.out.println("Exiting child thread.");
System.out.println(Thread.currentThread()); //gives the name of thread
}
}
class trial {
public static void main(String args[]) {
NewThreadt t=new NewThreadt();
NewThreadt q=new NewThreadt();
t.start();
q.start(); both are in main
System.out.println("Main thread exiting.");
}
}
输出:
Main thread exiting.
5
5
4
4
3
3
2
2
1
1
但是当我进行以下更改时,同步块起作用:
class NewThreadt implements Runnable //instead of class NewThreadt extends Thread
NewThreadt abc=new NewThreadt(); //Changes in main()
Thread t=new Thread(abc);
Thread q=new Thread(abc);
t.start();
q.start();
输出:
Main thread exiting.
5
4
3
2
1
5
4
3
2
1
为什么会这样?这两个例子不是应该一样工作吗?
同步依赖于共享一个公用锁。实例方法上的 synchronized
关键字意味着要使线程进入该方法,它首先必须获取 this
.
在你的第一个例子中没有共享锁,两个线程中的每一个都在锁定自己。每个线程获取自己的锁并且没有人阻塞,两个线程 运行 并发。 (这里唯一的锁定是,当一个线程想要写入控制台时,它必须首先获取控制台的锁,以便每个 println 以原子方式发生。)
在第二个示例中,相同的 Runnable 被传递到每个线程,因此它们都锁定在同一个对象上,即 Runnable。一个线程获取锁并执行,另一个必须等待第一个线程释放锁。
如果你改变第二个例子给每个线程一个单独的Runnable:
Thread t=new Thread(new NewThreadt());
Thread q=new Thread(new NewThreadt());
t.start();
q.start();
然后您会看到同步不起作用,它的行为与第一个示例相同。