我们可以在java中使用synchronized for run()方法吗?

时间:2012-05-26 14:55:27

标签: java multithreading synchronized

我们知道没有规定阻止多个线程使用run()方法调用start()方法。我创建了两个对象m1m2,它们都调用相同的线程来运行。

我需要通过在第二个对象执行开始之前调用线程来确保第一个对象完成(m1.start)它的执行。

我的问题是为什么我不能在我创建的帖子中使用synchronized关键字和run()方法(例如MyThread1)?

我尝试在我创建的线程中使用“synchronized”来运行run()方法,但它提供了任意输出(换句话说,m2不等待m1完成执行)

你可以在程序的最底部看到我得到的输出。

public class ExtendedThreadDemo {

    public static void main(String[] args) {    
        Mythread1 m1 =new Mythread1();
        Mythread1 m2 =new Mythread1();
        m1.start();
        m2.start();
        System.out.println(" main thread exiting ....");
    }
}

MyThread的

public class MyThread1 extends Thread {

    public synchronized void run() {
        for(int i=1; i<5; i++) {
            System.out.println(" inside the mythread-1 i = "+ i);
            System.out.println(" finish ");

            if (i%2 == 0) {
                try {
                    Thread.sleep(1000);
                } catch(InterruptedException e) {
                     System.out.println(" the thread has been interrupted ");
                }
            }
        }
    }
}

输出

main thread exiting ....
inside the mythread-1 i = 1
finish
inside the mythread-1 i = 2
finish 
inside the mythread-1 i = 1
finish 
inside the mythread-1 i = 2
finish 
inside the mythread-1 i = 3
finish 
inside the mythread-1 i = 4
finish 
inside the mythread-1 i = 3
finish 
inside the mythread-1 i = 4
finish 

正如您在i = 2之后看到的那样,第二个对象(即m2.start())开始执行。

3 个答案:

答案 0 :(得分:2)

在致电m1.join()之前致电main中的m2.start()

使方法synchronized仅影响对相同对象上的方法的多次调用; m1m2是不同的对象,因此添加synchronized将无效。

答案 1 :(得分:0)

此代码段:

public synchronized void run() {
  //code
}

在语义上等同于:

public void run() {
  synchronized(this) {
    //code
  }
}

请注意this参考。这意味着使用相同synchronized引用(锁定对象)的所有this块都是互斥的。但是,您要创建两个线程(对象),每个线程在不同的this引用上进行同步。

有几种方法可以改善您的代码:

仅使用一个Runnable并创建两个线程:

public class Mythread1 implements Runnable //...

然后:

Runnable r = new Mythread1();
Thread m1 = new Thread(r);
Mythread1 m2 = new Thread(r);

但是这只有在Mythread1 runnable是statelss时才有效,因为它将由两个线程共享。

使用相同的锁定实例

将一些任意lock对象传递给Mythread1的两个实例,然后使用:

synchronized(lock) {
  //code
}

从Java 5开始,有更复杂的方法来同步代码,但这个方法适用于简单的情况。

使用Thread.join()

您可以致电:

m1.start();
m1.join();
m2.start();

这样就可以了。

答案 2 :(得分:0)

同步实例方法仅阻止对该类的同一实例的并发访问。如果run方法是静态的,您会看到预期的效果。但我不建议将run方法设为静态。事实上,如果要保持其当前功能,则不能。您应该考虑使用m1.join()等待m1完成。如果您有多个要相互等待的线程,那么另一种更好的方法是使用CyclicBarrierCountDownLatch