我对同步块有疑问。执行以下代码后,我将输出为:
Inside run=>thread 2
Inside run=>thread 1
Inside run=>thread 1
Inside run=>thread 2
Inside run=>thread 2
Inside run=>thread 1
Inside run=>thread 2
Inside run=>thread 1
Inside run=>thread 1
Inside run=>thread 2
我期待输出,因为只有一个线程将首先执行synchronized块,然后只有第二个线程才能访问同步块。 我可能理解这个概念错了吗?
package com.blt;
public class ThreadExample implements Runnable {
public static void main(String args[])
{
System.out.println("A");
Thread T=new Thread(new ThreadExample());
Thread T1=new Thread(new ThreadExample());
System.out.println("B");
T.setName("thread 1");
T1.setName("thread 2");
System.out.println("C");
T.start();
System.out.println("D");
T1.start();
}
synchronized public void run()
{
for(int i=0; i<5; i++)
{
try
{
System.out.println("Inside run=>"+Thread.currentThread().getName());
Thread.currentThread().sleep(2000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
答案 0 :(得分:4)
每个线程都在不同的对象上进行同步。所以,是的,他们不会互相锁定。但更重要的是,run
方法是为Runnable
接口 定义的,没有 同步修饰符,您不应该向其添加一个({1}}方法正如你已经看到的那样,它没有你想象的效果。
要记住的关键是当你在方法上使用synchronized修饰符时:
public synchronized void someMethod();
与使用synchronized(this)
实际上是一回事。在这两种情况下,您都锁定了对象监视器。如果您有多个对象,则可以有多个监视器。
以下是您自己的示例的修改版本,它将按预期更有效。它使用公共对象监视器(在本例中为您的类本身),以便同步按预期工作:
public class ThreadExample implements Runnable {
public static void main(String args[]) {
System.out.println("A");
Thread T = new Thread(new ThreadExample());
Thread T1 = new Thread(new ThreadExample());
System.out.println("B");
T.setName("thread 1");
T1.setName("thread 2");
System.out.println("C");
T.start();
System.out.println("D");
T1.start();
}
public void run() {
synchronized (ThreadExample.class) {
for (int i = 0; i < 5; i++) {
try {
System.out.println("Inside run=>"
+ Thread.currentThread().getName());
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
答案 1 :(得分:3)
您的问题是,如果2个同步的块没有在同一台显示器上锁定,则它们不是互斥的。。
请记住,this
监视器上的同步方法会锁定 - 您的代码等同于:
public void run() {
synchronized(this) {
//your code here
}
}
由于您创建了两个ThreadExample
个实例,因此每个实例都有一个不同的this
。
您可以在两个线程中使用相同的锁来解决您的问题,例如:
public void run() {
synchronized(ThreadExample.class) {
//your code here
}
}
甚至更好,只根据Quoi指出的ThreadExample
创建一个实例。
答案 2 :(得分:1)
您创建了两个ThreadExample
对象,因此每个线程都有不同的synchronized
方法。
创建一个Object并将引用传递给线程,您将看到同步效果。:)
ThreadExample thex = new ThreadExample();
Thread T=new Thread(thex);
Thread T1=new Thread(thex);
这里两个线程都使用相同的synchronized
方法。
答案 3 :(得分:0)
呃,你正在同步每个线程的 run 方法。 Thread1不会尝试运行Thread2的run方法,反之亦然。这就是为什么它实际上与完全不同步一样。
答案 4 :(得分:0)
您正在创建该类的两个实例,并且您正在同步类,因此它们将独立运行,因为没有公共锁。他们将继续单独运行。