同步方法中的for循环

时间:2017-02-15 14:31:08

标签: 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());
        }
   }

 }
Output :
Running Thread-0
Running Thread-1
Running Thread-0
Running Thread-1
Running Thread-0
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-0
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0

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

请添加您的意见。

提前致谢。

3 个答案:

答案 0 :(得分:4)

  

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

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

public class TestThr implements Runnable {
   ...
   public synchronized void sync() {

在您的示例中,sync方法为synchronized,因此它将锁定TestThr的特定实例。你正在开始你的线程:

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

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

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

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

现在,2个线程正在TestThr的同一个实例上工作,因此它们将锁定在同一个对象上,输出将是您所期望的。

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

final Object lockObject = new Object();
Thread t = new Thread(new TestThr(lockObject));
Thread t1 = new Thread(new TestThr(lockObject));

然后在你的代码里面你会这样做:

public void sync() {
   synchronized (lockObject) {
      ...

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

顺便说一下,考虑到循环的大小,很可能一个线程可能启动并运行循环,然后在另一个线程开始之前退出。使用System.out.println(...)调用会降低线程速度,因此可能会引发争用,但如果删除输出则需要担心。由于线程之间的竞争条件,可能很难测试这样的线程程序。

答案 1 :(得分:3)

这是:

abcdefghij[enter]

的工作原理如下:

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

因此,在您的情况下,每个线程由不同的 public void sync(){ synchronize(this) { for (int i=0;i<10;i++){ System.out.println("Running "+Thread.currentThread().getName()); } } } 对象同步:

要查看预期输出,您可以尝试下一步:

TestThr

答案 2 :(得分:1)

正如@Pavlo Plynko所写,您使用的是synchronized方法,但是您为Thread创建了两个不同的对象。您应该创建单个实例,然后将此对象提供给您的线程。在这种情况下,两个线程将使用相同的object实例,并等待执行相同的方法。

以下代码:

public class TestThr implements Runnable {

public static void main(String[] args) {
    TestThr synchronizedObject = new TestThr();
    Thread t = new Thread(synchronizedObject);
    Thread t1 = new Thread(synchronizedObject);

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

@Override
public void run() {
    System.out.println("Thread " + Thread.currentThread().getName() + " is waiting for execution");
    sync();
    System.out.println("Thread " + Thread.currentThread().getName() + " has executed synced method");
}

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

将提供以下输出:

Thread Thread-0 is waiting for execution
Thread Thread-1 is waiting for execution
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Thread Thread-0 has executed synced method
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Thread Thread-1 has executed synced method