这些线程是否同步?

huangapple go评论72阅读模式
英文:

Are these Threads synchronized?

问题

我的任务是创建x个线程,并以某种方式使用MethodA和MethodB,并同步它们,最后捕获一些异常。
我知道这并不是对任务的真正清晰描述,但这就是我得到的任务。

所以问题是,这段代码是否能够完成任务要求的工作?
这些线程是否正确同步了?
英文:

My task is to create x Threads, and in some way to use MethodA and B, and synchronize them, and to catch some Exception in the end.
I know this is not a really good description of the task, but this is how I got the task.

So the question is, would this code do, what the task is asking for?
Are these Threads synchronized correctly or not?

public class Test2{

    public static synchronized void doActionA(){
        System.out.println("Hi");
    }

    public static synchronized void doActionB(){
        System.out.println("Hello");
    }

    public static void main(String[] args) {
        
        for(int i = 0; i < 10000; ++i){
            try{
                new Thread(() -> {
                    doActionA();
                    doActionB();
                }).start();  
            }catch(Exception e){
                e.printStackTrace();
            }finally{
                System.out.println(":)");
            }
        }
    }
}

答案1

得分: 1

这大部分是无用的,是的。

你有10000个线程。每个线程将执行以下任务模式:

NB:获取对象"Test2.class"(表示Test2类的java.lang.Class实例;在整个VM加载中只有一个这样的对象。我们将其称为“锁定器”。

  1. 检查锁定器对象的“监视器”线程。如果未设置,则将自己设置为锁定器的监视器线程并继续(并以原子方式执行所有操作)。如果没有设置,则将线程冻结,直到“监视器”再次为null,然后与其他9999个想要设置它的线程竞争;只有其中一个线程会获胜,将自己设置为监视器,并继续。其余的9998个将被冻结,并等待另一轮。

  2. 执行doActionA。与此同时,9999个线程正在虚度时光。

  3. 放弃锁定器(取消将自己设置为锁定器监视器的状态)。其他9999个线程都会争相设置自己为监视器。其中只有一个会“获胜”。

  4. 再次获取锁定(如果当前未设置自己为锁定器的监视器,则冻结并等待可用..并以原子方式执行)。根据JVM的实现方式,此线程实际上可能会“获胜”并重新获得监视器,击败其他9999个线程。

  5. 执行doActionB。在此任务期间,9999个线程无所作为,只是等待。

  6. 释放监视器并退出。噗。还有9999个要执行。

正如你所看到的,这个模式很可能意味着这段代码运行速度与以下代码相同:

for (int i = 0; i < 10000; i++) {
    doActionA();
    doActionB();
}

只不过上面的代码很可能运行得更快,因为你的示例首先分配了1.25 千兆字节的内存来存储堆栈(每个线程都需要一个堆栈,这里祈祷你的堆栈仅为128k,它们通常更大),并浪费了大量时间来操纵线程状态,几乎没有任何目的。

这不是正确的线程处理方式。

英文:

This is mostly useless, yeah.

You have 10000 threads. Each thread is going to perform the following task pattern:

NB: Take the object "Test2.class" (the instance of java.lang.Class that represents the Test2 class; there is only one such object in the entire VM loaded. We shall call this 'the locker'.

  1. Check the locker object for its 'monitor' thread. If it is unset, set yourself as the monitor thread of the locker and continue. (and do all that atomically). If not, freeze the thread until the 'monitor' is null again, and then compete with the 9999 other threads that want to set it; only one of the 9999 wins, sets itself as the monitor, and continues. The remainining 9998 will freeze and wait another round.

  2. Execute doActionA. All the while, 9999 threads are twiddling thumbs.

  3. Relinquish the locker (unset yourself as the monitor of the locker). 9999 other threads all fly in to set themselves as monitor. Only one of those will 'win'.

  4. Acquire the lock again (set yourself as the monitor of the locker if it is currently unset; otherwise, freeze and wait until it is available.. and do that atomically). Depending on the JVM implementation, this thread may in fact 'win', and take the monitor riiight back, beating the other 9999 threads.

  5. Execute doActionB. During this job, 9999 threads are twiddling thumbs doing absolutely nothing whatsoever. Just waiting around.

  6. Relinquish the monitor and exit. Pfew. 9999 more to go.

As you can tell, this pattern most likely means this code runs as fast as just:

for (int i = 0; i &lt; 10000; i++) {
    doActionA();
    doActionB();
}

except the above most likely runs FAR faster, as your example first allocates 1.25 gigabytes worth of memory just to store stacks (each thread needs a stack, and here's praying your stacks are 'just' 128k large, they are often larger), and wastes a ton of time juggling thread states for pretty much no purpose.

This is not how you thread things.

答案2

得分: 1

"这些线程是否正确同步或不正确同步?"

以何种方式"同步"?以何种目的"同步"?

如果程序能够保证执行您想要的操作,那么它是"正确的"。您希望这个程序做什么?

它将会做的是,它将打印一万行完整的"Hi",并且将打印一万行完整的"Hello",并且它们将以没有特定顺序的方式打印出来。每一行将会是完整的是因为System.out对象使用同步来确保最多只有一个线程可以执行println(...)。之所以这些行不会按照特定顺序打印,是因为程序中没有其他线程之间的同步。

英文:

> Are these Threads synchronized correctly or not?

"Synchronized" in what way? "Synchronized" for what purpose?

It's "correct" if the program is guaranteed to do what you want it to do. What do you want this program to do?

What it will do is, it will print print ten thousand complete lines of "Hi", and it will print ten thousand complete lines of "Hello", and it will print them in no particular order. The reason each line will be complete is that the System.out object uses synchronization to ensure that at most one thread at a time can execute println(...). The reason why the lines will be printed in no particular order is, there isn't any other synchronization between the threads in the program.

答案3

得分: 0

这是你的任务的主要部分:
在最后捕获一些异常。

问题是:这段代码能够完成任务所要求的吗?

不行,因为在线程内部发生的异常不能像这样在线程外部捕获,详细信息请阅读以下问题:

https://stackoverflow.com/questions/6546193/how-to-catch-an-exception-from-a-thread

英文:

This is the main part of your task:
catch some Exception in the end.

The question is: would this code do what the task is asking for?

No, becasue exception happened inside a thread can not be caught outside of the thread like this, read the following question for more information:

https://stackoverflow.com/questions/6546193/how-to-catch-an-exception-from-a-thread

huangapple
  • 本文由 发表于 2020年7月28日 03:34:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/63122307.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定