当前位置:网站首页>Synchronized description of concurrency
Synchronized description of concurrency
2022-06-26 17:10:00 【Under the seven kingdoms, I want 99】
Concurrent Synchronized explain
1 Monitor summary
Java Object head
With 32 For example, bit virtual machine :
Common object

Array objects

among Mark Word structure

The general composition is :
25 position hashcode + Generational age ( After several times of recycling, it still exists and then moves to the old age ) + Whether the bias lock is enabled (0 no 1 yes )+ Lock identification information
Lock logo :
01 It's not locked
00 Lightweight lock
10 Heavyweight lock
2 Monitor lock
Monitor, Also called monitor or tube side . Every Java Objects can be associated with a Monitor object , If Synchronized Lock the object ( heavyweight ) after , Of the object's head Mark Word The settings in point to Monitor Object pointer

explain :
- At first Monitor Medium Owner by null
- When a thread 2 perform synchronized(obj) Will be Monitor Owner Owner Set as thread 2, Monitor There can only be one of them Owner
- Threads 2 In the process of locking , If the thread 3, Threads 4, Threads 5 To carry out synchronized(obj), Will enter EntryList Blocked
- Threads 2 After executing synchronization code block contents , Will wake up EntryList The thread waiting in the , The competition is unfair ( Built in policies , It's not random )
synchronized Must be into the same object monitor It works
No addition synchronized Object does not manage monitors , Do not follow the rule
3 Synchronized Advanced
1 Lightweight lock
Use scenarios : If an object has multiple threads to lock , But the locking time is staggered ( There is no competition ), Then you can. Use lightweight locks to optimize .
Lightweight locks are transparent to users , That is, grammar is still synchronized
static final Object obj = new Object();
public static void method1() {
synchronized( obj ) {
// Synchronized block A
method2();
}
}
public static void method2() {
synchronized( obj ) {
// Synchronized block B
}
}
explain :
- 1 Create a lock record (Lock Record) object , Each thread's stack frame contains a lock record structure , Internal can store locked objects Mark Word

- 2 Let the lock record Object reference Point to the lock object , And try cas Replace Object Of Mark Word, take Mark Word Stored value Lock in record

- 3 If cas Replacement successful , The object header stores Lock records address and status 00 , Indicates that the thread locks the object , The diagram is as follows

- 4 If cas Failure , There are two situations
- If other threads already hold this Object Lightweight lock for , This shows that there is competition , Enter the lock expansion process
- If it's self executing synchronized Lock reentry , So add another one Lock Record As a count of reentry

- 5 When to exit synchronized Code block ( When the unlock ) If there is, the value is null Lock record of , It means there is re-entry , The lock record is reset , Express heavy Count minus one
![[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-ekWWkzV4-1656224885218)(assets/image-20220626092449488.png)]](/img/c5/89a0d2dfdba1c9568f980db0856c28.png)
- 6 When to exit synchronized Code block ( When the unlock ) The value of lock record is not null, Use this time cas take Mark Word Restore the value of to the object head
- success , Then the unlocking is successful
- Failure , It shows that lightweight lock has been expanded or upgraded to heavyweight lock , Enter the heavyweight lock unlock process
2 Lock expansion
If in the process of trying to add a lightweight lock ,CAS The operation cannot succeed , In this case, another thread has added a lightweight lock to the object ( Yes competition ), At this point, lock expansion is needed , Turn lightweight locks into heavyweight locks .
static Object obj = new Object();
public static void method1() {
synchronized( obj ) {
// Synchronized block
}
}
1 When Thread-1 When doing lightweight locking ,Thread-0 A lightweight lock has been applied to the object

2 At this time Thread-1 Failed to add lightweight lock , Enter the lock expansion process
- That is to say Object Object application Monitor lock , Give Way Object Point to heavyweight lock address
- Then go in on your own Monitor Of EntryList BLOCKED

- 3 When Thread-0 When the synchronization block is released , Use cas take Mark Word Restore the value of to the object header , Failure . At this time, it will enter the heavyweight unlocking technological process , Namely, in accordance with the Monitor Address found Monitor object , Set up Owner by null, Wake up the EntryList in BLOCKED Threads .
3 Spin optimization
When heavyweight locks compete , Spin can also be used to optimize , If the current thread spins successfully ( That is, at this time, the locking thread has exited synchronization block , Lock released ), At this point, the current thread can avoid blocking .
Successful cases

failures

explain :
- Spin will take up CPU Time , Single core CPU Spin is waste , Multicore CPU Spin is the only way to take advantage
- stay Java 6 After that, spin locking is adaptive , For example, the object has just had a successful spin operation , So I think the possibility of successful spin this time will high , Just spin a few more times ; conversely , Less spin, no spin , All in all , Comparative intelligence
- Java 7 After that, you can't control whether to turn on the spin function , That is, the bottom layer implements itself
4 Biased locking
Lightweight locks when there is no competition ( Just the thread itself ), Every reentry still needs to be executed CAS operation .
Java 6 Bias lock is introduced to do further optimization : Only for the first time CAS The thread ID Set to the object Mark Word head , And then I found out This thread ID It means there is no competition , There is no need to CAS. In the future, as long as there is no competition , This object is owned by the thread
static final Object obj = new Object();
public static void m1() {
synchronized( obj ) {
// Synchronized block A
m2();
}
}
public static void m2() {
synchronized( obj ) {
// Synchronized block B
m3();
}
}
public static void m3() {
synchronized( obj ) {
// Synchronized block C
}
}


Biased state
64 Bit object header format

When an object is created :
- If you open the bias lock ( Default on ), After the object is created ,markword The value is 0x05 In the end 3 Position as 101, Now it's thread、epoch、age All for 0
- The bias lock is delayed by default , It doesn't take effect immediately when the program starts , If you want to avoid delays , You can add VM Parameters - XX:BiasedLockingStartupDelay=0 To disable delay
- If the bias lock is not opened , After the object is created ,markword The value is 0x01 In the end 3 Position as 001, Now it's hashcode、 age All for 0, For the first time hashcode It will be assigned
1 Test delay
class Dog {
}
Using third-party tools jol View request header information
// Add virtual machine parameters -XX:BiasedLockingStartupDelay=0
public static void main(String[] args) throws IOException {
Dog d = new Dog();
ClassLayout classLayout = ClassLayout.parseInstance(d);
new Thread(() -> {
log.debug("synchronized front ");
System.out.println(classLayout.toPrintableSimple(true));
synchronized (d) {
log.debug("synchronized in ");
System.out.println(classLayout.toPrintableSimple(true));
}
log.debug("synchronized after ");
System.out.println(classLayout.toPrintableSimple(true));
}, "t1").start();
}
/* Running results : 11:08:58.117 c.TestBiased [t1] - synchronized front 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000101 11:08:58.121 c.TestBiased [t1] - synchronized in 00000000 00000000 00000000 00000000 00011111 11101011 11010000 00000101 11:08:58.121 c.TestBiased [t1] - synchronized after 00000000 00000000 00000000 00000000 00011111 11101011 11010000 00000101 */
After the object in the bias lock is unlocked , Threads id Still stored in the object header
Test disabled
In the above, the test code is added at runtime VM Parameters -XX:-UseBiasedLocking Disable bias lock
/* Running results : 11:13:10.018 c.TestBiased [t1] - synchronized front 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 11:13:10.021 c.TestBiased [t1] - synchronized in 00000000 00000000 00000000 00000000 00100000 00010100 11110011 10001000 11:13:10.021 c.TestBiased [t1] - synchronized after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 */
test hashCode
- The normal state object does not start with hashCode Of , The first call generates
2 revoke
1 Call object hashCode
Call object hashCode, But the object of the lock MarkWord Threads are stored in id, If the hashCode It will cause the deflection lock to be locked revoke
- Lightweight locks will be recorded in the lock record hashCode
- Heavyweight locks will be in Monitor It's recorded in hashCode
Calling hashCode After using the deflection lock , Remember to get rid of -XX:-UseBiasedLocking
/* 11:22:10.386 c.TestBiased [main] - call hashCode:1778535015 11:22:10.391 c.TestBiased [t1] - synchronized front 00000000 00000000 00000000 01101010 00000010 01001010 01100111 00000001 11:22:10.393 c.TestBiased [t1] - synchronized in 00000000 00000000 00000000 00000000 00100000 11000011 11110011 01101000 11:22:10.393 c.TestBiased [t1] - synchronized after 00000000 00000000 00000000 01101010 00000010 01001010 01100111 00000001 */
2 Objects used by other threads
When another thread uses a biased lock object , Will upgrade the biased lock to a lightweight lock
private static void test2() throws InterruptedException {
Dog d = new Dog();
Thread t1 = new Thread(() -> {
synchronized (d) {
log.debug(ClassLayout.parseInstance(d).toPrintableSimple(true));
}
synchronized (TestBiased.class) {
TestBiased.class.notify();
}
// If not wait/notify Use join The following comments must be opened
// because :t1 Thread cannot end , Otherwise, the underlying thread may be jvm Reuse as t2 Threads , Underlying thread id It's the same
/*try { System.in.read(); } catch (IOException e) { e.printStackTrace(); }*/
}, "t1");
t1.start();
Thread t2 = new Thread(() -> {
synchronized (TestBiased.class) {
try {
TestBiased.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug(ClassLayout.parseInstance(d).toPrintableSimple(true));
synchronized (d) {
log.debug(ClassLayout.parseInstance(d).toPrintableSimple(true));
}
log.debug(ClassLayout.parseInstance(d).toPrintableSimple(true));
}, "t2");
t2.start();
}
/* [t1] - 00000000 00000000 00000000 00000000 00011111 01000001 00010000 00000101 [t2] - 00000000 00000000 00000000 00000000 00011111 01000001 00010000 00000101 [t2] - 00000000 00000000 00000000 00000000 00011111 10110101 11110000 01000000 [t2] - 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 */
3 call wait/notify
public static void main(String[] args) throws InterruptedException {
Dog d = new Dog();
Thread t1 = new Thread(() -> {
log.debug(ClassLayout.parseInstance(d).toPrintableSimple(true));
synchronized (d) {
log.debug(ClassLayout.parseInstance(d).toPrintableSimple(true));
try {
d.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug(ClassLayout.parseInstance(d).toPrintableSimple(true));
}
}, "t1");
t1.start();
new Thread(() -> {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (d) {
log.debug("notify");
d.notify();
}
}, "t2").start();
}
/* [t1] - 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000101 [t1] - 00000000 00000000 00000000 00000000 00011111 10110011 11111000 00000101 [t2] - notify [t1] - 00000000 00000000 00000000 00000000 00011100 11010100 00001101 11001010 */
3 Bulk bias
If the object is accessed by multiple threads , But there's no competition , At this point, the thread is biased T1 There's still a chance for us to refocus T2, Reorientation resets the object Of Thread ID
When the undo bias lock threshold exceeds 20 Next time ,jvm I feel like this , I'm not biased in the wrong way , Then it will re bias to... When locking these objects Lock thread
private static void test3() throws InterruptedException {
Vector<Dog> list = new Vector<>();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 30; i++) {
Dog d = new Dog();
list.add(d);
synchronized (d) {
log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
}
}
synchronized (list) {
list.notify();
}
}, "t1");
t1.start();
Thread t2 = new Thread(() -> {
synchronized (list) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug("===============> ");
for (int i = 0; i < 30; i++) {
Dog d = list.get(i);
log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
synchronized (d) {
log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
}
log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
}
}, "t2");
t2.start();
}
4 Cancel in bulk
When the undo bias lock threshold exceeds 20 Next time ,jvm I feel like this , I'm not biased in the wrong way , Then it will re bias to... When locking these objects Lock thread
static Thread t1,t2,t3;
private static void test4() throws InterruptedException {
Vector<Dog> list = new Vector<>();
int loopNumber = 39;
t1 = new Thread(() -> {
for (int i = 0; i < loopNumber; i++) {
Dog d = new Dog();
list.add(d);
synchronized (d) {
log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
}
}
LockSupport.unpark(t2);
}, "t1");
t1.start();
t2 = new Thread(() -> {
LockSupport.park();
log.debug("===============> ");
for (int i = 0; i < loopNumber; i++) {
Dog d = list.get(i);
log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
synchronized (d) {
log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
}
log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
}
LockSupport.unpark(t3);
}, "t2");
t2.start();
t3 = new Thread(() -> {
LockSupport.park();
log.debug("===============> ");
for (int i = 0; i < loopNumber; i++) {
Dog d = list.get(i);
log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
synchronized (d) {
log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
}
log.debug(i + "\t" + ClassLayout.parseInstance(d).toPrintableSimple(true));
}
}, "t3");
t3.start();
t3.join();
log.debug(ClassLayout.parseInstance(new Dog()).toPrintableSimple(true));
}
5 Lock elimination
Case study
@Fork(1)
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations=3)
@Measurement(iterations=5)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class MyBenchmark {
static int x = 0;
@Benchmark
public void a() throws Exception {
x++;
}
@Benchmark
public void b() throws Exception {
Object o = new Object();
synchronized (o) {
x++;
}
}
}
Use the command to execute jar package : java -jar benchmarks.jar
Benchmark Mode Samples Score Score error Units
c.i.MyBenchmark.a avgt 5 1.542 0.056 ns/op
c.i.MyBenchmark.b avgt 5 1.518 0.091 ns/op
The execution time of the two methods is almost the same , because b Method, although the lock is added , But each lock object is inconsistent , Therefore, the system judges that the lock is invalid , That is, there is no locking effect .
Disable lock elimination
Carry out orders : java -XX:-EliminateLocks -jar benchmarks.jar
Benchmark Mode Samples Score Score error Units
c.i.MyBenchmark.a avgt 5 1.507 0.108 ns/op
c.i.MyBenchmark.b avgt 5 16.976 1.572 ns/op
b The method takes a long time .
Lock coarsening
Lock the same object multiple times , Causes multiple reentry of the thread , Lock coarsening can be used to optimize , This is different from the granularity of subdivision lock .
边栏推荐
- Count the number of each vowel letter in the string
- 分布式架构概述
- Wechat app mall, review products, upload commodity pictures, and score Commodity Services
- Platform management background and merchant menu resource management: merchant registration management design
- Teach you to learn dapr - 1 The era of net developers
- Platform management background and merchant menu resource management: access control design of platform management background
- Kubecon China 2021 Alibaba cloud special session is coming! These first day highlights should not be missed
- Some explanations for latex CJK
- Sandboxed container: container or virtual machine
- No manual prior is required! HKU & Tongji & lunarai & Kuangshi proposed self supervised visual representation learning based on semantic grouping, which significantly improved the tasks of target dete
猜你喜欢

Redis OM . Net redis object mapping framework

Microservice architecture practice: business management background and SSO design, SSO client design

Teach you to learn dapr - 4 Service invocation

The high concurrency system is easy to play, and Alibaba's new 100 million level concurrent design quick notes are really fragrant

20:第三章:开发通行证服务:3:在程序中,打通redis服务器;(仅仅是打通redis服务器,不涉及具体的业务开发)

Platform management background and merchant menu resource management: access control design of platform management background

Teach you to learn dapr - 5 Status management

Jouer avec Linux et installer et configurer MySQL facilement

Teach you to learn dapr - 3 Run the first with dapr Net program

Notes on flowus
随机推荐
Romance of the Three Kingdoms: responsibility chain model
Screenshot of the answers to C language exercises
JUnit unit test
Getting started with mongodb
去中心化NFT交易协议将击败OpenSea
Community ownership of NFT trading market is unstoppable
Quantitative contract system development analysis case - detailed explanation of contract quantitative system development scheme
What is the difference between digital collections and NFT
Leetcode 1170. Frequency of occurrence of the minimum letter of the comparison string (yes, solved)
7 views on NFT market prospect
Niuke Xiaobai monthly race 50
Microservice architecture practice: user login and account switching design, order query design of the mall
proxy
Jouer avec Linux et installer et configurer MySQL facilement
y=1/100*100+1/200*200+1/300*300+.....+ 1/m*m
Multiply the values of the upper triangular elements of the array by M
类型多样的石膏PBR多通道贴图素材,速来收藏!
Kubecon China 2021 Alibaba cloud special session is coming! These first day highlights should not be missed
[recommendation system learning] recommendation system architecture
No manual prior is required! HKU & Tongji & lunarai & Kuangshi proposed self supervised visual representation learning based on semantic grouping, which significantly improved the tasks of target dete