本文介绍了这三个线程在使用 Thread.yield() 时不会轮流吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了练习生锈的 Java,我想尝试一个简单的多线程共享数据示例,结果让我感到惊讶.

In an effort to practice my rusty Java, I wanted to try a simple multi-threaded shared data example and I came across something that surprised me.

基本上,我们在三个线程之间共享一个 AtomicInteger 计数器,每个线程轮流递增和打印计数器.

Basically we have a shared AtomicInteger counter between three threads that each take turns incrementing and printing the counter.

AtomicInteger counter = new AtomicInteger(0);

CounterThread ct1 = new CounterThread(counter, "A");
CounterThread ct2 = new CounterThread(counter, "B");
CounterThread ct3 = new CounterThread(counter, "C");

ct1.start();
ct2.start();
ct3.start();

反线程

public class CounterThread extends Thread
{
    private AtomicInteger _count;
    private String _id;

    public CounterThread(AtomicInteger count, String id)
    {
        _count = count;
        _id = id;
    }

    public void run()
    {
        while(_count.get() < 1000)
        {
            System.out.println(_id + ": " + _count.incrementAndGet());
            Thread.yield();
        }
    }
}

我期望当每个线程执行 Thread.yield() 时,它会将执行交给另一个线程以增加 _count 像这样:

I expected that when each thread executed Thread.yield(), that it would give over execution to another thread to increment _count like this:

A: 1
B: 2
C: 3
A: 4
...

相反,我得到的输出是 A 会将 _count 增加 100 次,然后将其传递给 B.有时所有三个线程会一致地轮流,但有时一个线程会主导几个增量.

Instead, I got output where A would increment _count 100 times, then pass it off to B. Sometimes all three threads would take turns consistently, but sometimes one thread would dominate for several increments.

为什么 Thread.yield() 不总是将处理交给另一个线程?

Why doesn't Thread.yield() always yield processing over to another thread?

推荐答案

在旋转的线程应用程序中,预测输出极其困难.您必须使用锁和其他东西做很多工作才能获得完美的 A:1 B:2 C:3 ... 类型输出.

In threaded applications that are spinning, predicting the output is extremely hard. You would have to do a lot of work with locks and stuff to get perfect A:1 B:2 C:3 ... type output.

问题在于,由于硬件、竞争条件、时间切片随机性和其他因素,一切都是竞争条件且不可预测的.例如,当第一个线程启动时,它可能会在下一个线程启动之前运行几毫秒.没有人可以 yield() 到.此外,即使它产生了,也许你在一个 4 处理器的机器上,所以根本没有理由暂停任何其他线程.

The problem is that everything is a race condition and unpredictable due to hardware, race-conditions, time-slicing randomness, and other factors. For example, when the first thread starts, it may run for a couple of millis before the next thread starts. There would be no one to yield() to. Also, even if it yields, maybe you are on a 4 processor box so there is no reason to pause any other threads at all.

相反,我得到的输出是 A 将 _count 增加 100 次,然后将其传递给 B.有时所有三个线程会一致地轮流,但有时一个线程会主导几个增量.

是的,通常在这种旋转循环中,您会在获得时间片时看到来自单个线程的输出突发.这也被 System.out.println(...)synchronized 的事实混淆了,这也会影响时间.如果它不做同步操作,你会看到更多的突发输出.

Right, in general with this spinning loops, you see bursts of output from a single thread as it gets time slices. This is also confused by the fact that System.out.println(...) is synchronized which affects the timing as well. If it was not doing a synchronized operation, you would see even more bursty output.

为什么 Thread.yield() 不总是将处理交给另一个线程?

我很少使用Thread.yield().它充其量只是对调度程序的一个提示,在某些架构上可能会被忽略.它暂停"线程的想法非常具有误导性.这可能会导致线程被放回到运行队列的末尾,但不能保证有任何线程在等待,因此它可能会继续运行,就像产量被删除一样.

I very rarely use Thread.yield(). It is a hint to the scheduler at best and probably is ignored on some architectures. The idea that it "pauses" the thread is very misleading. It may cause the thread to be put back to the end of the run queue but there is no guarantee that there are any threads waiting so it may keep running as if the yield were removed.

在此处查看我的答案以获取更多信息:多线程中不需要的输出

See my answer here for more info : unwanted output in multithreading

这篇关于这三个线程在使用 Thread.yield() 时不会轮流吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 17:13