简体   繁体   English

方法同步,但由于非序列化的线程行为,代码产生随机结果

[英]Method synchronized , but code produces random result due to non-serialized thread behaviour

Here is my code: 这是我的代码:

public class ThreadDemo {

public static void main(String args[]) throws Exception {
    Printer[] printers = new Printer[5];
    printers[0] = new Printer("@base");
    printers[1] = new Printer("#try");
    printers[2] = new Printer("!test");
    printers[3] = new Printer("^hello");
    printers[4] = new Printer("*world");

    for (Printer x : printers) {
        x.start();
    }

    try {
        for (Printer y : printers) {
            y.join();
        }
    } catch (InterruptedException e) {
        System.out.println(e);
    }
  }
}

class Printer extends Thread {
public Printer(String name) {
    super(name);
}

public void run() {
    print();
}

public synchronized void print() {
    for (int i = 0; i < 10; i++) {
        System.out.print(getName().charAt(0));
        try {
            sleep(100);
        } catch (InterruptedException e) {
            System.out.println(e + " occured");
        }
    }
  }
}

It results in 它导致了

@^!#**@^!#*#@!^@*#^!#^!*@^*@!#@!#*^@#^!*!@^#*#@*^! 

My expectation is that all symbols would be serialized as @@@@@^^^^^ based on which thread starts first. 我的期望是所有符号将根据首先启动的线程序列化为@@@@@ ^^^^^。

Calling sleep() would let other threads to proceed until sleeptime of current thread , but i guess that should not be the case with synchronized method. 调用sleep()会让其他线程继续进行直到当前线程的休眠时间,但我想不应该是同步方法的情况。

The synchronised doesn't come into play here. 同步在这里不起作用。

That keyword makes sure that you can't invoke the same method on the same object in parallel. 该关键字确保您不能并行地在同一对象上调用相同的方法。

You are invoking it on different objects, therefore the result would be the same even without the keyword in place! 您正在不同的对象上调用它,因此即使没有关键字,结果也会相同!

( I rather assume that the result you see is in fact caused by using println() here. That is a "really slow" operation that introduces "de facto" synchronisation when used by threads that are super-quick doing all their other work. I am trying to find some additional information about that, but that might take some more time ) (我宁愿假设您看到的结果实际上是由于在这里使用println()引起的。这是一个“非常慢”的操作,当超线程快速完成所有其他工作时,会引入“事实上的”同步。我试图找到一些关于它的其他信息,但这可能需要更多时间)

The issue with your code or I would say your expectation is that the method print is synchronized at the object level and you are creating new thread objects, starting the thread and calling this method. 您的代码或我的问题会说您的期望是方法print在对象级别同步,并且您正在创建新的线程对象,启动线程并调用此方法。

So in this case, each method is synchronized on each individual thread object. 因此,在这种情况下,每个方法在每个单独的线程对象上同步。 To achieve the behavior you expect, we can make the print method static and see the behavior change. 为了实现您期望的行为,我们可以使print方法保持静态并查看行为更改。 You will get the expected result because then, the method print is synchronized on a single instance of Printer class lock. 您将获得预期的结果,因为那时,方法print在一个Printer类锁实例上同步。 So even if different threads instance are calling this method, because there is a single lock for class, thread execution happens sequentially. 因此,即使不同的线程实例正在调用此方法,因为对于类只有一个锁,线程执行依次发生。

public static synchronized void print() {
    for (int i = 0; i < 10; i++) {
        System.out.print(Thread.currentThread().getName().charAt(0));
        try {
            sleep(100);
        } catch (InterruptedException e) {
            System.out.println(e + " occured");
        }
    }

}

@SolomonSlow - So it has to be corrected as 'No Synchronized methods' can be called on the same object at same time ? @SolomonSlow - 所以必须纠正为'同步方法'可以同时在同一个对象上调用吗?

There is only one thing you will ever need to know about a synchronized instance method. 关于同步实例方法,您只需要知道一件事。 You need to know that this... 你需要知道这......

synchronized void Foobar() { ... }

...Is just a shortcut way of writing a synchronized block. ...只是编写同步块的快捷方式。

void Foobar() {
    synchronized (this) {
        ...
    }
}

Both of those method declarations do exactly the same thing. 这两个方法声明都完全相同 So, everything you know or learn about how synchronized blocks behave can be applied to synchronized methods too. 因此,您知道或了解同步块行为的所有内容也可以应用于同步方法。

The most important thing to know about synchronized blocks is, "No two threads can ever be synchronized on the same object at the same time." 关于synchronized块的最重要的事情是,“不能同时在同一个对象上同步两个线程。” If you understand that, and if you know how a synchronized method is just a shortcut for a synchronized block, then you can answer your own question. 如果您了解这一点,并且如果您知道同步方法只是同步块的快捷方式,那么您可以回答自己的问题。

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

相关问题 如何使用kryoSerialzation将未序列化的对象存储到rediscache中 - How to Store non-serialized object into rediscache using kryoSerialzation 如果我从我的synchronized方法调用非同步方法是非同步方法线程安全吗? - if i call a non synchronized method from my synchronized method is non synchronized method thread safe? 线程调用同步方法是否使用相同的对象抢占另一个线程但是以非同步的方式? - Does a thread invoking, synchronized method, pre-empt another thread using same object but in a non synchronized manner? 如何在文件中写入非序列化对象(例如Shapes),以便以后可以读取它们 - How to write non-serialized objects, such as Shapes, in a file so they can then be read later 非同步方法可以被其他线程访问 - non-synchronized method can access by other thread,,,,,,, 编写静态同步方法(等待线程的结果) - Write a static synchronized method (wait for a result from thread) 调用同步方法时线程调用非同步实例方法 - Thread calling non-synchronized instance method when a synchronized method is called 同步方法中的线程锁定 - Thread locking in synchronized method 线程子类中的同步方法 - Synchronized method in thread subclass 多线程:同步方法的错误行为 - Multithreading: Wrong behaviour of synchronized method
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM