Talk about locks all the way

Posted by nick314 on Wed, 22 Dec 2021 07:31:22 +0100

Synchronized

I. Use

Modifier class: instance method, static method, code block;

Instance method: Lock object is the current instance object:

public synchronized void sayHello(){
	System.out.println("Hello World");
}

Static method: Lock object is the current class Class object:

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

Code block:

//Lock Object
synchronized(this){}
//Lock Object
synchronized(""){}
//Lock class
synchronized(xxx.class){}

2. Principles

2.1. Java Object Header

Common objects:

|--------------------------------------------------------------|
|                     Object Header (64 bits)                  |
|------------------------------------|-------------------------|
|        Mark Word (32 bits)         |    Klass Word (32 bits) |
|------------------------------------|-------------------------|

Array object:

|--------------------------------------------------------------|
|                     Object Header (64 bits)                  |
|------------------------------------|-------------------------|
|        Mark Word (32 bits)         |    Klass Word (32 bits) |
|------------------------------------|-------------------------|

Mark Word (32 bit, JVM 32 bit):

|-------------------------------------------------------|--------------------|
|                  Mark Word (32 bits)                  |       State        |
|-------------------------------------------------------|--------------------|
| identity_hashcode:25 | age:4 | biased_lock:1 | lock:2 |       Normal       |
|-------------------------------------------------------|--------------------|
|  thread:23 | epoch:2 | age:4 | biased_lock:1 | lock:2 |       Biased       |
|-------------------------------------------------------|--------------------|
|               ptr_to_lock_record:30          | lock:2 | Lightweight Locked |
|-------------------------------------------------------|--------------------|
|               ptr_to_heavyweight_monitor:30  | lock:2 | Heavyweight Locked |
|-------------------------------------------------------|--------------------|
|                                              | lock:2 |    Marked for GC   |
|-------------------------------------------------------|--------------------|

  • identity_hashcode: hashcode itself
  • age: There are only 4 generations with a maximum of 15, so -XX:MaxTenuringThreshold has a maximum of 15;
  • Thread: The thread ID of the bias lock
  • lock:: lock state marker bits, which represent as much information as possible with as few binary bits as possible. The value of this tag is different, and the meaning of the entire mark word is different.
  • biased_lock: Whether or not bias locks are enabled, 1 is enabled, 0 is not.
  • state:
    • Normal: Normal (stateless). lock:01; biased_lock:0
    • Biased: Deflection lock. Lock:01; biased_lock:1
    • Lightweight Locked: Lightweight lock. Lock:00;
    • Heavyweight Locked: Heavyweight lock. Lock:10;
    • Marked for GC:GC. lock: 11;

2.2, Monitor Monitor

  • WaitSet: Enter when the thread calls wait();
  • EntryList: Blocks the waiting queue.
  • Owner: The thread that acquired the lock.

todo: principle process:

3. Memory Visibility

Synchronized solves memory visibility issues and, when locked by synchronized, does the following:

  1. Acquire synchronization lock;
  2. Empty memory;
  3. Copy a new copy of the object from main memory to the worker thread;
  4. Continue executing code to refresh main memory data;
  5. Release synchronization lock;

4. Summary:

  • Atomicity is guaranteed;
  • Guarantees memory visibility; Get locks, get the latest from main memory; Release the lock and write the latest to main memory; Simply read the latest variables and use volatile;
  • Note Deadlocks: A and B threads hold A and B locks, waiting for B and A locks, respectively; Applications should be filed in sequence;
  • Reentrability: counter increases or decreases during reentry and exit;

volatile keyword

Memory visibility is when multiple threads share variables that access and manipulate the same, but when one thread modifies a shared variable, the other thread cannot be seen immediately or even forever.

In computer systems, except memory. Data is also cached in CPU registers and various caches. When accessing a variable, it may be fetched directly from the register or CPU cache, not necessarily in memory. When modifying a variable, it may also be written to the cache first, and then updated to memory synchronously later. In single-threaded programs, this is generally not a problem. But in multi-threaded programs, especially when there are many CPUs, this is a serious problem. One thread's modifications to memory are not visible to the other; the modifications are not synchronized to memory in a timely manner; and the other thread is not reading from memory at all.

Topics: Java Back-end Distribution Distributed lock lock