wordssynchronized

One, foreword

Synchronized is a surefire way to get started with Java locks, and being able to pronounce it can be a plus in future interviews (I’ve interviewed people who said “syn” instead of “syn”), but it’s a bit unprofessional. However the problem is not big, can use, understand the principle is the most important.

The content will go from simple to difficult, and sometimes you can give up some of the difficult things. I’ll mark it and it’ll be easier to see later

Second, the DEMO

Hello world!!

Example: Xiaoqiang and Xiaoming live together, but there is only one toilet, they have to do every day is to grab the pit, so how to use the code implementation to write?

/ * * *@authorDay and night of Muzi * < P > * Human entity class */
public class Person {
    / / name
    private String name;
    / / go to the bathroom
    public void gotoWc(a) {
        Wc.useWc(this);
    }
    public String getName(a) {
        return name;
    }
    public void setName(String name) {
        this.name = name; }}/ * * *@authorMuzi day and night * * Toilet entity class */
public class Wc {
    /** * How to use the toilet *@paramP People who use toilets */
    public static void useWc(Person p){
        try{
            System.out.println(p.getName()+"Using the toilet!!");
            TimeUnit.SECONDS.sleep(10);
            System.out.println(p.getName()+"It's gone!!");
        } catch (Exception e) {
            // The toilet has to be finished in case it breaks down
            System.out.println(p.getName()+"It's gone!!"); }}}/ * * *@authorWood of day and night * this test is small strong and small bright to discuss good say small strong you come to small strong finish thing small bright again * this won't produce conflict because be to discuss good order to carry out * everybody knows order is won't give what problem */
public class SyncTest {
    public static void main(String[] args) {
        // Cockroaches
        Person xiaoqiang = new Person();
        xiaoqiang.setName("Small strong");

        // Xiaoming object
        Person xiaoming = new Person();
        xiaoming.setName("Xiao Ming");

        / / go to the bathroomxiaoqiang.gotoWc(); xiaoming.gotoWc(); }}Copy the code

Toilet-going process:

What if the two go their own way without discussion?

/ * * *@authorDay and night of wood */
public class SyncTest02 {
    public static void main(String[] args) {
        // Cockroaches
        Person xiaoqiang = new Person();
        xiaoqiang.setName("Small strong");

        // Xiaoming object
        Person xiaoming = new Person();
        xiaoming.setName("Xiao Ming");

        // Start two threads and let them do their own work
        new Thread(()->xiaoqiang.gotoWc()).start();
        newThread(()->xiaoming.gotoWc()).start(); }}Copy the code

Toilet-going process:

The picture above is obviously visible, xiaoqiang did not finish it, Xiaoming went up, if the small still gather together live, how to do big? The picture thinks ~~

At this point you’re probably thinking, is there a lock on the bathroom door? Can’t someone just go in and lock it up?

Bingo!

/ * * *@authorMuzi's day and night * * After the transformation of the toilet entity class */
public class Wc {
    /** * Synchronized: Lock the toilet if you use it first!! *@paramP People who use toilets */
    public static synchronized void useWc(Person p){
        try{
            System.out.println(p.getName()+"Using the toilet!!");
            TimeUnit.SECONDS.sleep(10);
            System.out.println(p.getName()+"It's gone!!");
        } catch (Exception e) {
            // The toilet has to be finished in case it breaks down
            System.out.println(p.getName()+"It's gone!!"); }}}/ * * *@authorDay and night of wood */
public class SyncTest02 {
    public static void main(String[] args) {
        // Cockroaches
        Person xiaoqiang = new Person();
        xiaoqiang.setName("Small strong");

        // Xiaoming object
        Person xiaoming = new Person();
        xiaoming.setName("Xiao Ming");

        // Open two threads, neither of whom can do their own work.
        Lock whoever comes in first
        new Thread(()->xiaoqiang.gotoWc()).start();
        newThread(()->xiaoming.gotoWc()).start(); }}Copy the code

Toilet-going process:

It can be seen that Xiaoqiang finished first and Xiaoming went up again, so that there would be no problem.

Some people may ask, only locked, did not unlock, xiao Ming how to get in?

This is a feature of synchronized, which releases the lock automatically after the code in the synchronized package is executed.

So avoid forgetting to release the lock, bring embarrassment ~

Pretend academic discussions

3.1 Why is it locked?

Take the toilet, for example, for yourself. Come up with the word “shared resources.

3.2 Object Lock Class lock

1) An object lock, as its name implies, locks an object

/ * * *@authorMuzi night and day * object lock */
public class SyncObject {

    /** * Cumulative value (shared resource) */
     int count = 0;
    /** * lock object */
    private Object lock = new Object();

    public static void main(String[] args) {
        SyncObject so = new SyncObject();

        / / thread 1
        new Thread(()->{
            try {
                for(;;) { TimeUnit.SECONDS.sleep(2); so.increaseCount(); }}catch (Exception e) {
                System.err.println("Error"); }},Thread 1 "").start();

        / / thread 2
        new Thread(()->{
            try {
                for(;;) { TimeUnit.SECONDS.sleep(2); so.increaseCount(); }}catch (Exception e) {
                System.err.println("Error"); }},Thread 2 "").start();
    }

    /** * count adds */
    public void increaseCount(a){
        / / lock
        synchronized (lock){
            count = count+1;
            System.out.println(Thread.currentThread().getName()+" count="+count); }}}Copy the code

In this example, two threads increment count and lock the object. This is called an object lock.

Synchronized (this) what is this? This is the current object, which is also the object lock,

Synchronized (this) is the equivalent of adding synchronized to a method, both of which are the current objects of the lock

    /** * count adds */
    public void increaseCount(a){
        / / lock
        synchronized (this){
            count = count+1;
            System.out.println(Thread.currentThread().getName()+" count="+count); }}/** * count */
    public synchronized void  increaseCount02(a){
            count = count+1;
            System.out.println(Thread.currentThread().getName()+" count="+count);
    }
Copy the code

2) Class locking, as the name implies, is to lock a class

After each Class is loaded into memory, it generates an object lock of type Class

It’s actually locking an object but it’s a special object, it’s a class

/ * * *@authorMuzi night and day * object lock */
public class SyncObject03 {

    /** * Cumulative value (shared resource) */
    static int count = 0;
    /** * lock object */
    private Object lock = new Object();

    public static void main(String[] args) {
        SyncObject03 so = new SyncObject03();

        / / thread 1
        new Thread(()->{
            for (;;){
                SyncObject03.increaseCount();
            }
        },Thread 1 "").start();
        
        / / thread 2
        new Thread(()->{
            for (;;){
                SyncObject03.increaseCount();
            }
        },Thread 2 "").start();

    }

    /** * count adds */
    public synchronized static void increaseCount(a){
        / / lock
        try {
            count = count+1;
            System.out.println(Thread.currentThread().getName()+" count="+count);
            TimeUnit.SECONDS.sleep(1);
        } catch (Exception e){
            System.err.println("Wrong!"); }}/** * count adds */
    public   void increaseCount02(a){
        synchronized(SyncObject03.class){
            / / lock
            try {
                count = count+1;
                System.out.println(Thread.currentThread().getName()+" count="+count);
                TimeUnit.SECONDS.sleep(1);
            } catch (Exception e){
                System.err.println("Wrong!"); }}}}Copy the code

Both of these methods are class locks.

3.3 Can the unlocked method of the current object be executed when the locked method is executed?

This is a tip of the toe answer, but many interviewers ask it. Asked after you meng ~~ can’t?

The answer is: yes!

Why is it possible? Because of love so love ~~ wrong, again.. Because can so can ~~

Xiao Ming is eating, give a lock to the bowl, others can not use, that xiao Ming can watch his idol DENG Zi Chess singing at the same time?

If anyone says no, he will not be allowed to play with mobile phones, pads or computers during meals. Let him eat (it’s a pig)

/ * * *@authorDay and night * possible interview questions */
public class SyncObject04 {


    private Object lock = new Object();

    public static void main(String[] args) throws InterruptedException {
        SyncObject04 so = new SyncObject04();

        / / thread 1
        new Thread(()->{
            so.increaseCount();
        },Thread 1 "").start();

        Thread.sleep(2000);

        / / thread 2
        new Thread(()->{
            so.lookMv();
        },Thread 2 "").start();
    }

    /** * eat */
    public void increaseCount(a){
        / / lock
        synchronized (this) {try{
                System.out.println("吃饭 ");
                // You can also chat with girls here
                chatWithGirl();
                TimeUnit.SECONDS.sleep(10);
            } catch (Exception e) {
                System.err.println("I dropped my food on the floor.");
            }
            System.out.println("After dinner"); }}/** * watch the concert video */
    public  void  lookMv(a){
        System.out.println("Watch the concert video");
    }
    
    /** ** ** /
    public  void  chatWithGirl(a){
        System.out.println("Talk to a beautiful woman."); }}Copy the code

3.4 reentrant

Can you sum it up in one sentence?

Cough: The same thread can call two methods with the same lock without blocking.

Example: The same person can use the same pair of chopsticks (chopsticks locked) and eat different dishes ~~

Eat fish to get the lock, in the eat fish method call eat salad method, is able to call success because the two methods use the same lock

/ * * *@authorDay and night of wood */
public class TestC {
    /** * One chopstick can only be used by one person at a time (one thread) */
    Object chopsticks   = new Object();

    public static void main(String[] args) {
        TestC c = new TestC();
        new Thread(()->{
            c.eatFish();
        }).start();

    }

    / * * * * /
    public void eatFish( ) {
        synchronized (chopsticks) {
           try {
              System.out.println("Fish");
              Thread.sleep(2000);
              eatSalad();
           } catch (Exception e){ }
        }
    }

    /** * Eat salad */
    public void eatSalad(a) {
        synchronized (chopsticks) {
            try {
                System.out.println("Eat salad");
                Thread.sleep(2000);
                eatFish();
            } catch (Exception e){ }
        }
    }
}

Copy the code

3.5 Underlying Implementation

(1) Simple version of

Synchronized was a heavyweight lock before jdk1.6. Is every lock will go to the operating system to apply for a lock.

Jdk1.6 and later upgrade for locks

The simple idea is:

Synchronized (object)

  1. Thread A is the first to access
  2. The bias lock only records the thread ID of thread A in the Markword of object
  3. If thread A comes in and looks at the thread number of the Markword, it can use it
  4. And then thread B comes in, and thread B looks at me, right? Someone’s taking the lock!
  5. Thread B will loop and wait, like knocking on the bathroom door and asking thread A how are you? Knock on the door and ask thread A how are you? Knock on the door and ask thread A how are you? Knock on the door and ask thread A how are you?
  6. This operation on thread B will be called, in technical terms, a spin lock
  7. After asking thread B 10 times, it will upgrade to heavyweight lock if it can’t get the lock.
  8. No lock -> bias lock -> spin lock -> Heavyweight lock
  9. Lock like.. Upgrade, not downgrade

(2) Complex version

  1. CAS brief description to understand the introduction

What is ABA problem, if you have a wife, I say if ~ take stealing pocket money for example

www.processon.com/view/link/6…

This is a story: Xiao Qiang stole pocket money to invite Xiao Ming to dinner story

ABA is:

Xiao Qiang’s wife leaves home with 100,000 yuan (A)

Jack Bauer stole 10,000 yuan and left 90,000 yuan (B)

Xiaoqiang borrows 10,000 yuan from Xiaoyue and puts back 100,000 yuan in total (A)

Xiaoqiang wife came back to see 100 thousand, very satisfied. But what she doesn’t know is that this is a job swap

Then Xiaoqiang’s wife read my blog and found out the secret. What should she do?

Keyword: version Version number

Before she went to work, she wrote a version in pen on her family’s savings, which would change if Jack Bauer stole the money again and returned it (+1).

This solves the ABA problem

  1. Locked process

Severe competition: It takes too long to select too many waits

New objects may be anonymously biased directly (if bias locking is turned on by default) because there is no bias to any thread, so it is anonymously biased

The JVM does not enable bias locking by default until a delay of 4 seconds is enabled

  1. New What does an object look like?What’s markword

1. View tools: JOL (Java Object Layout)

Direct maven import is ready to use

<dependencies>
    <dependency>
        <groupId>org.openjdk.jol</groupId>
        <artifactId>jol-core</artifactId>
        <version>0.9</version>
    </dependency>
</dependencies>
Copy the code
/ * * *@authorDay and night of wood */
public class Person {
    long  money;

    public long getMoney(a) {
        return money;
    }

    public void setMoney(long money) {
        this.money = money; }}/ * * *@authorDay and night of wood */
public class JolTest {
    public static void main(String[] args) {
        Person p = newPerson(); System.out.println(ClassLayout.parseInstance(p).toPrintable()); }}// Output the result
Person object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 
      4     4        (object header)                           00 00 00 00 
      8     4        (object header)                           43 c1 00 f8 
     12     4        (alignment/padding gap)                  
     16     8   long Person.money                              0
Instance size: 24 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total

Copy the code

Yi? I thought it was synchronized?

2. markword

I lock the object p and print layout to see that the markword has changed

So the lock information is recorded in markWord

/ * * *@authorDay and night of wood */
public class JolTest {
    public static void main(String[] args) {
        Person p = new Person();
        System.out.println(ClassLayout.parseInstance(p).toPrintable());

        synchronized(p) { System.out.println(ClassLayout.parseInstance(p).toPrintable()); }}}Copy the code

Is MarkWord that good? No! It could be worse. Let’s see what kind of information it contains

First look at the last 3bit other not very understand this time can compare the above layout output take a look

It started with 01 and then changed to 00 (no bias lock switched to lightweight lock)

First, the last 2 bits:


00: Lightweight lock spin lock

Spin locking, which consumes CPU resources, is operated in user mode and is not associated with kernel mode. Two threads compete to put their Lock Record in MarkWord. Who is the first to put the Record in Markword, who is the first to get the Lock, the other person then cas to put the RecordCopy the code

What does a Lock Record point to a markword that is unlocked

So that explains why hashCode doesn’t get lost because there’s a backup record, right

So this is lock reentrant: as mentioned above, lock reentrant, every time the lock goes in, it adds an LR and starting with the second LR it points to a NULL

By the time the lock exits, that is, at Monitorexit, LLR -1, LLR -1 keeps decreasing, decreasing and decreasing


10: Heavyweight lock

This pointer is stored in markWord (Java is an address or ID).

Heavyweight locks, all waiting in a queue, consume less CPU

Reentrant lock: The heavyweight is the record on a property of the Object Moniter

When to upgrade to heavyweight lock:

Before jdk1.6 -xx :PreBlockSpin can adjust the number of updates for more than 10 times. After JDk1.6, adaptive Self Sping is added The JVM controls itselfCopy the code

11:GC collects tags


01: Look at the third from the bottom

001: no lock

101: bias lock thread ID, c++ implementation is used pointer


Synchronized is compiled into bytecode with two words monitorenter monitorexit

When does monitorexit run out of code, or an exception occurs which is how synchronized automatically releases locks

4. Why do you need heavyweight locks when you have spin locks

(1) Spin consumes CPU resources. If the lock time is long or there are many spin threads, THE CPU will be consumed

(2) Heavyweight locks have a wait queue. All those who cannot get the lock enter the wait queue without consuming CPU resources

5. Is bias locking necessarily more efficient than spin locking?

(1) Not necessarily when you know there must be multithreaded contention and biased locking involves lock undo, when spin locking is better

(2) The JVM starts with many threads competing, so bias locking is not enabled by default and will be enabled after some time

(3) – XX: BiasedLockingStartupDelay = 0, the default is 4 seconds


Finally, I attached my wechat official account. I just started to make wishes and make progress together.

Note: the above text only represents personal views, only for reference, if there is a problem, please point out immediately even roll out of bed to correct.