[英]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.