Do these three threads not alternate when using Thread.yield ()?

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

Basically, we have a common AtomicInteger counter between three threads, each of which incrementally increments and prints a counter.

Main

 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(); 

Counterthread

 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(); } } } 

I expected that when each thread executed Thread.yield() , it would pass the execution to another thread to increase _count as follows:

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

Instead, I got a conclusion where A would _count 100 times and then pass it to B Sometimes all three threads will alternate alternately, but sometimes one thread will dominate for several increments.

Why Thread.yield() not always process another thread?

0
source share
2 answers

I expected that when each thread executes Thread.yield (), it will pass over another thread to increase _count as follows:

In streaming applications that spin, predicting output is extremely difficult. You will need to work a lot with locks and other materials to get an excellent conclusion like A:1 B:2 C:3 ...

The problem is that everything is a race condition and unpredictable due to hardware, race conditions, randomness in time and other factors. For example, when the first thread starts, it can start for a couple of milliseconds before the next thread starts. No one will yield() to. In addition, even if it gives, you may be on a 4-processor box, so there is no reason to stop any other threads.

Instead, I got a conclusion where A will increment the counter 100 times and then pass it to B. Sometimes all three threads will alternate sequentially, but sometimes one thread will dominate in several increments.

Correctly, in general, with these spinning cycles, you see bursts of output from a single thread when it receives temporary fragments. It also confuses the fact that System.out.println(...) is synchronized , which also affects time. If he did not perform a synchronized operation, you would see an even greater output.

Why does Thread.yield () always return processing to another thread?

I very rarely use Thread.yield() . At best, this is a hint at the scheduler and is probably ignored on some architectures. The idea that it "pauses" a stream is very misleading. This may cause the thread to be returned to the end of the execution queue, but there is no guarantee that there are any threads that expect it to continue to work as if the output was deleted.

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

+2
source

Let's read javadoc , will we?

A hint to the scheduler that the current thread is ready to give its current processor usage. The scheduler may ignore this prompt.

[...]

It is rare to use this method. This can be useful for debugging or testing, where it can help reproduce errors due to race conditions. It can also be useful when designing concurrency with control constructs such as those found in java.util.concurrent.locks.

You cannot guarantee that another processor will receive the processor after yield() . It is up to the planner, and it seems that he / she does not want in your case. Instead, you can consider sleep() ing, for testing.

+1
source

All Articles