This article is participating in the Java Theme Month – Java Debug Notes EventActive link

preface

Do not know when to start, I write articles become cautious, perhaps is afraid of their knowledge is not enough, perhaps is afraid of the depth is not enough. In fact, I clearly know is afraid that no one likes. I’m not going to write the rest of the article. Then I’m not afraid.

Java operator literacy

This article is mainly to practice the operators described above. If you don’t understand, please read this article first. Thank you.

About state values in source code in thread pools

The following is the thread pool source code about the state value, looking at a lot of operators are dizzy, the source code is completely unable to read. I’m stuck in a place I don’t understand until I figure it out.

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

// runState is stored in the high-order bits
private static final int RUNNING    = -1 << COUNT_BITS;
private static final int SHUTDOWN   =  0 << COUNT_BITS;
private static final int STOP       =  1 << COUNT_BITS;
private static final int TIDYING    =  2 << COUNT_BITS;
private static final int TERMINATED =  3 << COUNT_BITS;

// Packing and unpacking ctl
private static int runStateOf(int c)     { return c & ~CAPACITY; }
private static int workerCountOf(int c)  { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }

Copy the code

This whole bunch of operators, just to serve the AtomicInteger CTL object in your code, the thread pool, that’s the value that holds two values by way of an operational offset. The core purpose is to reduce lock competition. Let’s take a look at AtomicInteger

AtomicInteger

Unsafe is an atomically updated int value. The underlying implementation uses the Unsafe compareAndSwapInt, which atomically sets the current value to the given updated value if == the expected value. Returns true on success. Returning False indicates that the actual value is not equal to the expected value.

The problem is, it’s just an Integer. How to save two? Doug Lea, the author, uses an operator to store two values. The Integer state is 32 bits. The TERMINATED state is RUNNING, SHUTDOWN, STOP, TIDYING, and TERMINATED. A maximum of seven threads are stored in three digits. Note: but including 0, plus a negative number, is a maximum of seven states. Because you want to make sure that your numbers are high, the low values are overwritten. The lower 29 bits hold the number of threads currently running (workerCountOf), and the maximum is 536870911. So the number of threads is limited by this value. I think no one should set up such a big bar! Hey hey

Just to get a sense of it

I’m going to peel these lines of code.

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

// The higher 3 bits store the state, and the lower 29 bits store the number of threads currently running

private static final int COUNT_BITS = Integer.SIZE – 3;

ReentrantReadWriteLock = 16; // ReentrantReadWriteLock = 16; // ReentrantReadWriteLock = 16;

private static final int CAPACITY = (1 << COUNT_BITS) – 1;

// This is the key value, which is used to divide a value. CAPACITY is not easy to write, its binary, 1 is 29, 1111111111111111, if COUNT_BITS is 16, substitution (1 < < COUNT_BITS) – 1), is a low fill 16 0, minus 1, the result is 16 1, and if it is 2, That’s two ones.

Thread status value

// runState is stored in the high-order bits

private static final int RUNNING = -1 << COUNT_BITS;

private static final int SHUTDOWN = 0 << COUNT_BITS;

private static final int STOP = 1 << COUNT_BITS;

private static final int TIDYING = 2 << COUNT_BITS;

private static final int TERMINATED = 3 << COUNT_BITS;

The key is to look at this table, mainly the first three digits.

state Binary (32 bits) The former three The decimal system
RUNNING 11100000000000000000000000000000 111 – 536870912.
SHUTDOWN 00000000000000000000000000000000 000 0
STOP 00100000000000000000000000000000 100 536870912
TIDYING 01000000000000000000000000000000 010 1073741824
TERMINATED 01100000000000000000000000000000 011 1610612736

Calculates thread pool state

Looking back on the previous content, I think I should forget almost, I can look up the information, I never remember, my mind is for me to think.

The result is 1 only if the middle bit of both operands is 1, otherwise the result is 0.

~ is 0 becomes 1,1 becomes 0.(simply add one, then take the inverse) for example, 3, add one, is 4, take the inverse is -4. Please refer to my previous chapter for a more intuitive detailed calculation. Thanks – (· ω ·) Blue

Use the RUNNING state to calculate

Private static int runStateOf(int c) {//CAPACITY =536870911, After ~ is - 536870912 / / CAPACITY against hexadecimal is 11100000000000000000000000000000 / / RUNNING in hexadecimal is 11100000000000000000000000000000 / / results Hexadecimal is 11100000000000000000000000000000 / / todo: result is consistent with the RUNNING, knock, so here is take the high return of c & ~ CAPACITY; }Copy the code

Count the number of running threads

Let’s assume that the current number of threads RUNNING is 1 and the RUNNING status of the thread is RUNNING.

Private static int workerCountOf (int) c {/ / CAPACITY base is 00011111111111111111111111111111 / / 536870911-536870911 - thread count is 1 Hexadecimal is 11100000000000000000000000000001 / / result base is 00000000000000000000000000000001 / / & two operands, bit is 1, the result is 1, Otherwise the result is 0 //todo: key, so here is the low value. return c & CAPACITY; }Copy the code

Since CAPACITY is high at 000, (&) is 29 bits lower either way.

Update the thread pool running status

Or operator USES the symbol “|”, two bits as long as there is a 1, then the result is 1, otherwise 0.

private static int ctlOf(int rs, int wc) {

// For example, the current state is RUNNING and the number of threads is 1. So the value is

//1110 0000 0000 0000 0000 0000 0000 0001

//0000 0000 0000 0000 0000 0000

//1110 0000 0000 0000 0000 0000 0000 0001 //

return rs | wc; }

conclusion

Next post, write a thread pool by hand!

My knowledge is limited, if there is any wrong description, I would like to correct.

Look at thisLooks like you owe me a thumbs-up. Thank you.

Your praise is like the warm sun in winter, warming the heart.