java-锁 synchroinized & lock

Thread safety problem: The problem caused by multi-threading modification of stateful and mutable shared variables.

Locks are required to solve thread safety issues.

 

Locks: thread mutual exclusion, memory visibility.

        Thread Mutual Exclusion: Guarantees sequential access to stateful mutable shared variables.

                 Only the thread can access the variable when the lock is obtained. After the thread releases the lock, other threads can obtain the lock.

This is the process of thread acquiring lock-"read-write variable--"release lock--next thread--acquire lock-"read-write variable--".

Memory visibility: After entering the lock, the variable is read from the main memory, not from the cache, and the modified variable is written back to the main memory before the lock is released.

            Valid data for the variable fetched from main memory after the next thread acquires the lock.

 1. Similarities

1. Mutual exclusion and visibility 

synchronized: java syntax, reentrant lock

   1. JVM controls thread mutual exclusion

   2. JVM controls memory visibility (variables modified in synchronized code blocks are written back to main memory)

  

 

 ReentrantLock: java class, reentrant lock 

   1. Use Unsafe.park or Unsafe.unPack to block or wake up threads to control the sequential execution of threads.

   2. Visibility guarantee: internally holds a volatile variable state:

           When locked, read the state, invalidate the cache, and read the data from the main.

           When unlocked, the state is written, and the data in the cache is written back to the main memory.

   

2. Both are reentrant locks

3. Support unfair locks (ReentrantLock supports unfair locks and fair locks, and synchronized is an unfair lock. The performance of unfair locks is higher than that of fair locks)

 

2. Differences

1. Writing

   a. synchronized can be used on static methods, instance methods, and code blocks without the need for the host to release the lock

       On the lock code block, you need to actively release the lock in finally lock.unlock()

2. Fairness

       ReentrantLock supports fair and unfair locks, and synchronized is an unfair lock

3. Lock waiting and interruption

      synchronized : When the lock is occupied, wait until the lock is acquired. -- does not support interrupts

      Lock.lock() : When the lock is held, wait until the lock is acquired. -- does not support interrupts

      Lock.tryLock() : Returns false immediately when the lock is occupied.--Interrupts are not supported

      Lock.tryLock(long time, TimeUnit unit): When the lock is occupied, wait for the specified time, if the lock has not been acquired, return false

                                                                     -- Support interrupts.

      Lock.lockInterruptibly() : : When the lock is occupied, wait until the lock is acquired.--Support interrupt

  

 4. Lock the range

       synchronized : The same monitor object, which can be a class instance or a static class. (same memory address)

       Lock : the same Lock instance

    

 

 

 

 

 

 

Performance comparison:

8 logical CPUs, enabling multiple threads to count from 0 + 1

The competition is very fierce: (the execution time in the lock is about 0.05ms) The total target value is: 1000000000
16 threads:
Use synchronized: use time: 132 seconds, total value: 1000000000, print thread status during execution: 1 thread running, 15 threads blocking java.lang.Thread.State: BLOCKED (on object monitor)
Using ReentrantLock: use time: 39 seconds, total value: 1000000000, printing thread status during execution: 1 thread running, 15 threads blocking java.lang.Thread.State: WAITING (parking)
Use CAS spin lock: not executed, reason: it will be executed for a long time, 8 cpus are 100%, I am afraid that the cpu will be burned out.


4 threads:
Use synchronized: use time: 139 seconds, total value: 1000000000, print thread status during execution: about 70% of 4 cpus, 1 thread running, 3 threads blocking java.lang.Thread.State: BLOCKED (on object monitor)
Use ReentrantLock: use time: 43 seconds, total value: 1000000000, print thread status during execution: about 40% of 4 cpus, 1 thread running, 3 threads blocking java.lang.Thread.State: WAITING (parking)
Use CAS spin lock: use time: a long time, total value: 1000000000, print thread status during execution: 4 cpu 100%, 4 threads running,

1 thread:
Use synchronized: use time: 29 seconds, total value: 1000000000, print thread status during execution: 1 cpu 100%, 1 thread running,
Use ReentrantLock: use time: 23 seconds, total value: 1000000000, print thread status during execution: 1 cpu 100%, 1 thread running,
Use CAS spin lock: use time: 17 seconds, total value: 1000000000, print thread status during execution: 1 cpu 100%, 1 thread running,


The competition is not fierce: (the execution time within the lock is about 0.05ms, the sleep in the lock (1ms), the sleep between the two locks (1ms)) The total target value is: 100000
4 threads: (equivalent to 2 threads grab a lock)
Using synchronized: use time: 111 seconds, total value: 100000, very low cpu
Using ReentrantLock: use time: 112 seconds, total value: 100000, very low cpu
Using CAS spinlock: use time: 110 seconds, total value: 100000, 4 cpu 50%

16 threads: (equivalent to 8 threads grabbing a lock)
Using synchronized: use time: 112 seconds, total value: 100000, very low cpu
Using ReentrantLock: use time: 112 seconds, total value: 100000, very low cpu
 


32 threads: (equivalent to 16 threads grabbing a lock)
Using synchronized: use time: 112 seconds, total value: 100000, very low cpu
Using ReentrantLock: use time: 112 seconds, total value: 100000, very low cpu
 

256 threads: (equivalent to 128 threads grabbing a lock)
Using synchronized: use time: 112 seconds, total value: 100000, very low cpu
Using ReentrantLock: use time: 112 seconds, total value: 100000, very low cpu

Performance Analysis:
CAS spin lock: Rarely, there is competition, and the execution time in the lock is less than 1ms--the case is used. be careful!
In general, synchronized has the same performance as ReentrantLock.
When the competition is extremely fierce and the thread blocks and wakes up frequently in a very short period of time, using ReentrantLock has better performance.

 

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326645217&siteId=291194637