简体   繁体   English

为什么在此示例中使用同步(Java并发)是不正确的?

[英]Why this is not right by using synchronized (Java concurrency) in this example?

I have two Java classes as below... 我有两个如下的Java类...

(1) JavaClass SyncTest: It defines a class (implementing Runnable) and invokes a "synchronized" method (named "call") defined in Class SyncTestCalled (1)JavaClass SyncTest:它定义一个类(实现Runnable)并调用在SyncTestCalled类中定义的“同步”方法(名为“ call”)

(2) JavaClass SyncTestCalled : There is one synchronized method. (2)JavaClass SyncTestCalled:有一种同步方法。

------
    After calling from main(), I am thinking it should output something like:  
[Two]
[Three]
[One]

But, it outputs something like this (note the open bracket which is not paired in right locations) : 

[[[Two]
Three]
One]

What's wrong with the codes? 代码有什么问题? Please help. 请帮忙。 Thanks a lot! 非常感谢!


    Here is the code of these two classes...


    public class SyncTest implements Runnable {    
        Thread t;   
        String name;
        SyncTestCalled syncTestCalled;    
        public SyncTest(String name) {
                t = new Thread(this, name);
                syncTestCalled = new SyncTestCalled();
                this.name = name;
                t.start();
        }    
        public void run() {             
                syncTestCalled.call(this.name);
        }       
        public static void main(String[] args) {
                SyncTest syncTest1 = new SyncTest("One");
                SyncTest syncTest2 = new SyncTest("Two");
                SyncTest syncTest3 = new SyncTest("Three");
        }   
      } // of class SyncTest
    public class SyncTestCalled {
        public SyncTestCalled() {
        // Do nothing
        }    
        synchronized public void call(String message) {
                System.out.print("[");
                try {
                     Thread.sleep(1000);
                     System.out.print(message);
                } catch (InterruptedException e) { 
                     e.printStackTrace();
                }
                System.out.println("]");
        }
    } // of class SyncTestCalled

When you use synchronized as part of the method declaration, Java attempts to acquire the monitor (lock) on the object the method is invoked on. 当您将synchronized作为方法声明的一部分使用时,Java会尝试在调用该方法的对象上获取监视器(锁)。 So a method like 所以像

synchronized public void call(String message) {
    ...
}

is equivalent to 相当于

public void call(String message) {
    synchronized (this) {
        ...
    }
}

In your code, you create three different SyncTestCalled objects and pass each individual one to the different SyncTest instances. 在您的代码中,您将创建三个不同的SyncTestCalled对象,并将每个对象传递给不同的SyncTest实例。 In other words, nothing is coordinated. 换句话说,什么都不协调。 Each call to 每次致电

syncTestCalled.call(this.name);

is synchronized on a different object and therefore none of the threads need to wait on the others. 在另一个对象上同步,因此没有一个线程需要等待其他线程。

It's up to the Thread scheduler who gets where first, so you get output like 这取决于线程调度程序首先到达的位置,因此您将获得如下输出

[[[Two]
Three]
One]

or 要么

[[[OneThree]
Two]
]

Note that Thread.sleep(long) does not relinquish any monitors the thread currently has. 请注意, Thread.sleep(long)不会放弃该线程当前具有的任何监视器。

Only one thread can invoke your call() method on a given instance at any given time. 在任何给定时间,只有一个线程可以在给定实例上调用call()方法。 But what you want is atomicity for several calls to System.out.print() methods. 但是,您想要的是对System.out.print()方法的多次调用的原子性。 For that, you need to acquire a lock on System.out instead: 为此,您需要获取对System.out的锁定:

synchronized (System.out) {
  System.out.print('[');
  System.out.print(message);
  System.out.println(']');
}

Because PrintStream locks on itself, this will prevent other threads from interleaving their own calls to print() . 由于PrintStream自身锁定,因此可以防止其他线程交错自己对print()的调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM