同步方法中的for循环

Bha*_*Vre 1 java multithreading synchronization

我试图理解java中的同步。我有以下示例

public class TestThr implements Runnable {

   public static void main(String[] args) {

            Thread t=new Thread(new TestThr());
            Thread t1=new Thread(new TestThr());

            t.start();
            t1.start();
   }

   @Override
   public void run() {
        sync();
   }

   public synchronized void sync(){
         for (int i=0;i<10;i++){
            System.out.println("Running "+Thread.currentThread().getName());
        }
   }

 }
Run Code Online (Sandbox Code Playgroud)
输出:
运行线程-0
运行线程1
运行线程-0
运行线程1
运行线程-0
运行线程1
运行线程1
运行线程1
运行线程-0
运行线程1
运行线程1
运行线程1
运行线程1
运行线程1
运行线程-0
运行线程-0
运行线程-0
运行线程-0
运行线程-0
运行线程-0

From above example I was expecting one thread(whoever enter first) will complete the iteration and then second will start and complete but I'm getting inconsistent output .

Please add your opinion .

Thanks in advance.

Gra*_*ray 5

从上面的示例中,我期望一个线程(无论谁先输入)将完成迭代,然后第二个线程将开始并完成,但是输出不一致。

您得到的输出是您不理解的,但它与您编写的代码一致。当您有一个synchronized方法时,您将锁定封闭类的实例。

public class TestThr implements Runnable {
   ...
   public synchronized void sync() {
Run Code Online (Sandbox Code Playgroud)

在您的示例中,sync方法是synchronized这样,它将锁定的特定实例TestThr。您正在像这样启动线程:

Thread t = new Thread(new TestThr());
Thread t1 = new Thread(new TestThr());
Run Code Online (Sandbox Code Playgroud)

这意味着每个线程都有其自己的实例,TestThr因此它们锁定在不同的实例上,并且不会彼此停止运行。

如果您改为执行以下操作:

final TestThr testThr = new TestThr();
Thread t = new Thread(testThr);
Thread t1 = new Thread(testThr);
Run Code Online (Sandbox Code Playgroud)

现在,这两个线程正在的同一实例上工作,TestThr因此它们将锁定在同一对象上,并且您的输出将达到您的期望。

这仅适用,因为TestThr没有存储任何字段。如果您需要一个更复杂的类,那么我将锁对象传递给他们。就像是:

final Object lockObject = new Object();
Thread t = new Thread(new TestThr(lockObject));
Thread t1 = new Thread(new TestThr(lockObject));
Run Code Online (Sandbox Code Playgroud)

然后,在您的代码中执行以下操作:

public void sync() {
   synchronized (lockObject) {
      ...
Run Code Online (Sandbox Code Playgroud)

因此,该方法不会被锁定,但是您将在共享锁定对象上进行同步。

顺便说一句,考虑到循环的大小,一个线程很有可能会启动并运行循环,然后在另一个线程甚至启动之前退出。把System.out.println(...)通话将放缓线程下来,也许你会拿到争,但你需要有关担心,如果你删除的输出。由于线程之间的竞争条件,可能很难测试这样的线程程序。