线程实例的创建和销毁(Java)

3

我正在学习Java线程(同步和锁定),但是我不知道这两者之间的区别。

// Two different instances of SyncExample
Thread a1 = new Thread(new SyncExample(), "A");
Thread b1 = new Thread(new SyncExample(), "B");

// Same instance is passed to both the threads
SyncExample syn = new SyncExample();
Thread a2 = new Thread(syn, "A");
Thread b2 = new Thread(syn, "B");

// I believe in total 4 stacks are built.
a1.start();
b1.start();

a2.start();
b2.start();

public class SyncExample implements Runnable {

    Object obj = new Object();

    @Override
    public void run() {

        this.myName();
    }

    private void myName() {

        synchronized (obj) {
            System.out.print("Define" + Thread.currentThread().getName());
            try {
                Thread.sleep(500);
            } catch (InterruptedException ex) {
                System.out.println(ex);
            }
            System.out.print("tly" + Thread.currentThread().getName());
        }
        System.out.println(" Maybe" + Thread.currentThread().getName());
    }
}


public class SyncExample implements Runnable {

    Object obj = new Object();

    @Override
    public void run() {

        this.myName();
    }

    private void myName() {

        synchronized (obj) {
            System.out.print("Define" + Thread.currentThread().getName());
            try {
                Thread.sleep(500);
            } catch (InterruptedException ex) {
                System.out.println(ex);
            }
            System.out.print("tly" + Thread.currentThread().getName());
        }
        System.out.println(" Maybe" + Thread.currentThread().getName());
    }
}

但问题在于,当我使用以下代码运行此示例时:

1 - 相同的参考输出是:

DefineAtlyA MaybeA
DefineBtlyB MaybeB

2 - 2个不同的实例:


DefineADefineBtlyAtlyB MaybeB
 MaybeA

有人能解释一下,当我们将可运行目标传递给线程类时会有什么区别吗? 1. 相同实例 2. 不同实例

2个回答

2
在你的代码中,当你传递两个不同的实例(SyncExample类的实例)时,每个实例都有自己的锁对象(由变量obj持有)。由于存在两个不同的锁对象,因此每个线程都会获取一个锁并并行执行,导致线程A和B的输出交错出现(DefineADefineBtlyAtlyB MaybeB MaybeA)。
而当你传递相同的实例时,只有一个SyncExample类的实例。因此,只有一个锁对象的实例(由变量obj持有)。因此,这个锁对象将在两个线程之间共享。由于这种共享,只有一个线程(比如T1)能够进入同步块;另一个线程(比如T2)将等待T1退出同步块。因此,在你的执行中,你会先看到线程A的所有打印语句,然后是线程B的所有语句(DefineAtlyA MaybeA DefineBtlyB MaybeB)。
如果我要概括这一点:当你传递不同的实例时,只有静态变量会影响线程的并行执行,但当你传递单个实例时,静态和类级变量(例如你代码中的obj变量)都会影响线程的并行执行。

哇,这解释了一切。我很困惑,一直以为 obj 获取了线程 A 的锁,实际上恰恰相反。感谢您的评论。 - Gagandeep Singh

1
输出应该提示您它们之间的差异。
当您将相同的SyncExample传递给两个不同的线程时,只有其中一个线程能够获取obj上的锁并执行synchronized块中的代码。
当您传递两个不同的SyncExample对象时,这两个线程都能够同时执行,因为它们在不同的对象上进行同步。

我可以从输出中得到这个,但我的问题是为什么和如何? - Gagandeep Singh
你说的“为什么”是什么意思?你有了解过同步和synchronized关键字吗? - Andrew Logvinov
我相信Kshitij的评论已经让我一切都清楚了。是的,我对这些概念并不清楚,所以才会提出问题。感谢你的帮助,Andrew Logvinov。 :-) - Gagandeep Singh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接