Thread.join和Synchronized有什么区别?

时间:2014-12-02 08:14:20

标签: java multithreading thread-synchronization

我很困惑何时使用Thread.join()以及何时在多线程应用程序中使用synchronization

据我所知,他们都阻止或等待执行由其他一些线程完成。
这个例子必须输出10个A,10个B& 10 C依次序列模式,如:

1  : A
2  : A
3  : A
4  : A
5  : A
6  : A
7  : A
8  : A
9  : A
10 : A
1  : B
2  : B
3  : B
4  : B
5  : B
6  : B
7  : B
8  : B
9  : B
10 : B
1  : C
2  : C
3  : C
4  : C
5  : C
6  : C
7  : C
8  : C
9  : C
10 : C
----ProGraM ENDS----

示例从此处开始

class SyncTest extends Thread 
{   
    StringBuffer sb;

    public SyncTest(StringBuffer sb) 
    {
        this.sb = sb;   
    }

    public void run()
    {
        synchronized(sb) 
        {
            for(int i=1;i<=10;i++){
                System.out.println(i+" : "+sb.charAt(0));
            }
            sb.setCharAt(0, (char) (sb.charAt(0)+1));
        }
    }

    public static void main(String [] args) throws InterruptedException
    {
        StringBuffer sb = new StringBuffer("A");
        Thread t1=new SyncTest(sb);
        Thread t2=new SyncTest(sb);
        Thread t3=new SyncTest(sb);

        t1.start();

        t2.start();

        t3.start();

        Thread.sleep(1000);

        System.out.println("----ProGraM ENDS----");
    }
}

这里,输出结果是10 A,接着是10 B,然后按顺序排列10 C。但我也可以使用Thread.join代替synchronized块来获得相同的输出:

public void run()
    {
        //removed synchronized statement...

            for(int i=1;i<=10;i++){
                System.out.println(i+" : "+sb.charAt(0));
            }
            sb.setCharAt(0, (char) (sb.charAt(0)+1));

    }

    public static void main(String [] args) throws InterruptedException
    {
        StringBuffer sb = new StringBuffer("A");
        Thread t1=new SyncTest(sb);
        Thread t2=new SyncTest(sb);
        Thread t3=new SyncTest(sb);

        t1.start();
        t1.join();
        t2.start(); // wait for t1 to complete
        t2.join();
        t3.start(); // wait for t2 to complete
        t3.join(); 

                     // wait for t3 to complete
        System.out.println("----ProGraM ENDS----");
    }

任何人都可以清楚我对使用这两种技术的困惑,即什么时候使用Thread.join以及何时在Java上进行多线程使用synchronization

5 个答案:

答案 0 :(得分:13)

Thread.join()等待线程完全完成,而synchronized块可用于防止两个线程同时执行同一段代码。

一般来说,建议何时使用其中一个是很困难的,因为它们用于不同的目的。很难找到一个例子,例如你的代码,两者之间的差异很小。

话虽如此,在您的第一个示例中,无法保证输出将按字母顺序排列。您无法确定哪个线程将首先进入synchronized块。所以在这种特殊情况下,join()是最合适的。

答案 1 :(得分:5)

thread.join()停止执行当前线程,直到联接的线程完成..您已正确评论.. :))

同步可防止多个线程在同一实例上执行代码的同步部分。

答案 2 :(得分:3)

synchronized关键字启用一种锁定机制,允许线程不相互踩踏。 Java文档将此描述为“防止线程干扰和内存一致性错误”的方法。

如果使用join(),它确保一旦线程调用join,当前线程(正在运行的线程)将不会执行,除非您调用join的线程已完成。我认为下面的图表可能有助于更好地形象化。

enter image description here

Source

答案 3 :(得分:2)

没有join()线程并行运行并且取决于OS时间片(首先开始)。 join()个线程串联运行。例如: 假设您有两个线程同时调用join()方法

MyThread t1 = new MyThread();
MyThread t2 = new MyThread();

t1.join(); // this will be start first.
t2.join(); // this will be start only after above.

现在没有join()方法,t1t2中的任何一个都可以先启动。这不是保证。

synchronized statement / keyword用于监视线程,因此一次只有一个线程可以访问该同步的方法/变量。如果您使用join(),则无关紧要。

如果您将synchronizedjoin()一起使用,则可以保证线程t1只能首先访问。如果没有synchronizedt1t2线程都可以随时访问,但这些线程会启动并死掉。因join()而串联。

答案 4 :(得分:0)

简单示例:

你有一个静态字符串表,其中一些线程将放置一些值。 该表初始化为“empty”。使用静态索引访问该表。 如果一个线程放置一个值,它将增加静态索引。

如果同步线程,它将确保线程放置的任何值都不能被另一个线程覆盖。

如果你在线程上使用连接,只有第一个连接线程有机会将值放在表中。另一个将等待但是知道索引递增后它们将无法访问表(null指针异常)。所以Join使另一个线程无用。

此示例在包含synchronized方法的同一实例上使用线程。