JUC Series (1 & 2): Thread basics, production and consumption models, 8-lock problem

It was discovered that the JUC series of the Study Mad God is missing the opening chapter and is hereby reissued.

Threads and processes

Threads, processes, how to explain

Process: A program such as QQ.exe Music.exe A collection of programs

A process can contain multiple threads, at least one thread

Java defaults to opening two threads main GC

Thread: open a process such as: typora writing, automatic saving (thread is responsible)

For Java, there are three methods we have learned to create threads: Thread, Runnable, Callable

PS :Java本身是无法开启线程的!!!

    public synchronized void start() {
    
    
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
    
    
            start0();
            started = true;
        } finally {
    
    
            try {
    
    
                if (!started) {
    
    
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
    
    
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

	// 本地方法 调用底层的 C++ Java本身不能直接操作硬件
    private native void start0();

Concurrency, parallelism

If we want to learn concurrent programming, we must first understand: What are concurrency and parallelism?

Concurrency (multiple threads operating the same resource)

  • One CPU core can simulate multiple threads. The only martial arts in the world is fast and fast alternation.

Parallel (multiple programs run together)

  • CPU multi-core, multiple threads execute simultaneously; if you need to improve performance: Thread pool

Check your cpu core count

image-20220301201453940

The essence of concurrent programming: making full use of CPU resources

All companies attach great importance to efficiency, such as layoffs: one great one can be greater than two less powerful ones or even more

For example: The speed of doing things for experts: 1s, for ordinary people: 10s. The speed of 1s is definitely faster and more efficient;

Although the number of personnel (reduced) has increased, technical capabilities have increased.

How many states does a thread have?

You can see this through the properties in the enumeration class: State in the Thread source code.

Threads have six states

    public e
num State {
    
    
        //新的线程
        NEW,
        //运行中
        RUNNABLE,
        // 阻塞
        BLOCKED,
        //等待,一直等
        WAITING,
        //等待一段时间就不等了
        TIMED_WAITING,
        // 终止线程
        TERMINATED;
    }

The difference between wait/sleep

1. They come from different categories

wait => object

sleep => Thread

2. About lock release

wait will release the lock, sleep will not release the lock

Abstract understanding: sleep cannot be released while asleep, wait is waiting, and release when someone needs it

wait must be used in a synchronized code block, and there must be someone who needs to wait.

sleep can be used anywhere

3. Do you need to catch exceptions?

wait does not need to catch exceptions

sleep needs to catch exceptions

LockLock

TraditionalSynchronized

Traditional train ticket case

/**
 * @projectName: JUC
 * @package: Thread
 * @className: SaleTicketDemo
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 * @date: 2022/3/1 20:28
 * @version: 1.0
 */
public class SaleTicketDemo {
    
    
    /**
     * 真正的多线程开发 公司中的需要降低耦合性
     * 线程就是一个单独的资源类,没有任何附属的操作
     * 1、 属性。方法
     * */
    public static void main(String[] args) {
    
    
        //并发: 多线程操作同一个资源类,把资源丢入线程
        Ticket ticket = new Ticket();
        new Thread(() -> {
    
    
            for (int i = 0; i < 40; i++) {
    
    
                ticket.sale();
            }
        }, "A").start();
        new Thread(() -> {
    
    
            for (int i = 0; i < 40; i++) {
    
    
                ticket.sale();
            }
        }, "B").start();
        new Thread(() -> {
    
    
            for (int i = 0; i < 40; i++) {
    
    
                ticket.sale();
            }
        }, "C").start();
    }
}

//资源类 OOP
class Ticket {
    
    
    //属性 方法
    private int number = 50;

    //    买票的方式
    public synchronized void sale() {
    
    
        if (number > 0) {
    
    
            System.out.println(Thread.currentThread().getName() + "卖出了" + (number--) + "票,剩余" + number);
        }
    }
}

Lock interface

image-20220301204107904

Some commonly used implementation classes

image-20220301204151242

image-20220301204430613

Fair lock: Very fair, it can be done on a first-come, first-served basis. For example, the first thread needs to execute for 30 seconds, and the following thread needs 3 seconds. The latter must wait for the former to finish executing.

Unfair lock: Very unfair, the queue can be jumped based on conditions

How to use Lock to write a train ticket demo

  1. new ReentrantLock();
  2. Lock.lock(); unlock
  3. finally => lock.unlock(); unlock

The difference between Synchronized and Lock

  1. Synchronized built-in java keyword, Lock is a java class
  2. Synchronized cannot obtain the status of the lock. Lock can determine whether the lock has been obtained.
  3. Synchronized will automatically release the lock. Lock must be unlocked manually. If the lock is not released, it will be deadlocked.
  4. Synchronized thread 1 (obtains the lock, blocks), thread 2 (waits, waits until death), Lock locks may not wait
  5. Synchronized Reentrant lock, cannot be interrupted, unfair, Lock Reentrant lock, lock can be judged, manual adjustment
  6. Synchronized is suitable for locking a small amount of code synchronization problems, Lock is suitable for locking a large amount of synchronized code

What is a lock and how to determine who is locked

producer and consumer issues

Producer and Consumer Issues:Synchronized Edition

Frequent interview: singleton mode, sorting algorithm, producer and consumer deadlock

package ProduceAndconsum;

/**
 * @projectName: JUC
 * @package: ProduceAndconsum
 * @className: A
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 * @date: 2022/3/1 21:08
 * @version: 1.0
 */
public class A {
    
    
    public static void main(String[] args) {
    
    
        Data data = new Data();
        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                try {
    
    
                    data.increment();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }, "A").start();
        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                try {
    
    
                    data.decrement();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }, "B").start();
    }
}

//数字 资源类
// 1、 判断等待,通知
class Data {
    
    
    private int number = 0;

    //    +1
    public synchronized void increment() throws InterruptedException {
    
    
        if (number != 0) {
    
    
            //    等待
            this.wait();
        }
        number++;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        //    通知其他线程 +1 完毕了
        this.notifyAll();
    }

    //    -1
    public synchronized void decrement() throws InterruptedException {
    
    
        if (number == 0) {
    
    
            //    等待
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        //    通知其他线程 -1 完毕了
        this.notifyAll();
    }
}

However, after writing this simple model, the interviewer will still find faults. What is the problem?

Question, now we have two threads, if we add four threads A, B, C, and D, is it still safe? The answer is definitely no

False wake-up problem: When we increase the output of four threads, we will find some problems. The output is no longer 0101.

image-20220301212425229

image-20220301212149214

How to solve it here? Replace if with a while loop

After modification, according to the explanation of the official document, if was adapted into while

image-20220301212605922

The output returns to normal

package ProduceAndconsum;

/**
 * @projectName: JUC
 * @package: ProduceAndconsum
 * @className: A
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 * @date: 2022/3/1 21:08
 * @version: 1.0
 */
public class A {
    
    
    public static void main(String[] args) {
    
    
        Data data = new Data();
        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                try {
    
    
                    data.increment();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }, "A").start();
        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                try {
    
    
                    data.decrement();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }, "B").start();
        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                try {
    
    
                    data.increment();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }, "C").start();
        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                try {
    
    
                    data.decrement();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }, "D").start();
    }
}

//数字 资源类
// 1、 判断等待,通知
class Data {
    
    
    private int number = 0;

    //    +1
    public synchronized void increment() throws InterruptedException {
    
    
        while (number != 0) {
    
    
            //    等待
            this.wait();
        }
        number++;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        //    通知其他线程 +1 完毕了
        this.notifyAll();
    }

    //    -1
    public synchronized void decrement() throws InterruptedException {
    
    
        while (number == 0) {
    
    
            //    等待
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        //    通知其他线程 -1 完毕了
        this.notifyAll();
    }
}

Producer and Consumer Issues: JUC Edition

In new learning, synchronized is replaced by Lock

So who will replace wait and notify?

image-20220301212829262

Find Condition through Lock

image-20220301213020385

image-20220301213059259

package ProduceAndconsum;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @projectName: JUC
 * @package: ProduceAndconsum
 * @className: B
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 * @date: 2022/3/1 21:31
 * @version: 1.0
 */


public class B {
    public static void main(String[] args) {
        Data2 data = new Data2();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "C").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "D").start();
    }
}

//数字 资源类
// 1、 判断等待,通知
class Data2 {
    private int number = 0;
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    //等待
    //    condition.await();
    //唤醒全部
    //    condition.signalAll();

    //    +1
    public void increment() throws InterruptedException {
        lock.lock();
        try {
            while (number != 0) {
                //    等待
                condition.await();
            }
            number++;
            System.out.println(Thread.currentThread().getName() + "=>" + number);
            //    通知其他线程 +1 完毕了
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    //    -1
    public void decrement() throws InterruptedException {
        lock.lock();
        try {
            while (number == 0) {
                //    等待
                condition.await();
            }
            number--;
            System.out.println(Thread.currentThread().getName() + "=>" + number);
            //    通知其他线程 -1 完毕了
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}
package ProduceAndconsum;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @projectName: JUC
 * @package: ProduceAndconsum
 * @className: B
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 * @date: 2022/3/1 21:31
 * @version: 1.0
 */


public class B {
    
    
    public static void main(String[] args) {
    
    
        Data2 data = new Data2();
        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                try {
    
    
                    data.increment();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }, "A").start();
        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                try {
    
    
                    data.decrement();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }, "B").start();
        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                try {
    
    
                    data.increment();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }, "C").start();
        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                try {
    
    
                    data.decrement();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }, "D").start();
    }
}

//数字 资源类
// 1、 判断等待,通知
class Data2 {
    
    
    private int number = 0;
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    //等待
    //    condition.await();
    //唤醒全部
    //    condition.signalAll();

    //    +1
    public void increment() throws InterruptedException {
    
    
        lock.lock();
        try {
    
    
            while (number != 0) {
    
    
                //    等待
                condition.await();
            }
            number++;
            System.out.println(Thread.currentThread().getName() + "=>" + number);
            //    通知其他线程 +1 完毕了
            condition.signalAll();
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            lock.unlock();
        }
    }

    //    -1
    public void decrement() throws InterruptedException {
    
    
        lock.lock();
        try {
    
    
            while (number == 0) {
    
    
                //    等待
                condition.await();
            }
            number--;
            System.out.println(Thread.currentThread().getName() + "=>" + number);
            //    通知其他线程 -1 完毕了
            condition.signalAll();
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            lock.unlock();
        }
    }
}

Any new technology cannot simply replace the old technology. It must be optimized and supplemented.

Condition

image-20220301214146773

After we changed the code, the output can be normal but it is still confusing. We want to achieve the output of A->B->C->D, which leads to new knowledge points.

Condition precise wake-up

package ProduceAndconsum;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @projectName: JUC
 * @package: ProduceAndconsum
 * @className: B
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 * @date: 2022/3/1 21:31
 * @version: 1.0
 */


public class C {
    
    
    public static void main(String[] args) {
    
    
        Data3 data = new Data3();
        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                data.printA();
            }
        }, "A").start();
        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                data.printB();
            }
        }, "B").start();
        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                data.printC();
            }
        }, "C").start();
    }
}

//数字 资源类
// 1、 判断等待,通知
class Data3 {
    
    
    private int number = 1;
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    Condition condition1 = lock.newCondition();
    Condition condition2 = lock.newCondition();

    public void printA() {
    
    
        lock.lock();
        try {
    
    
            //    业务,判断 执行 通知
            while (number != 1) {
    
    
                //等待
                condition.await();
            }
            System.out.println(Thread.currentThread().getName() + "=>AAA");
            number = 2;
            condition1.signal();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            lock.unlock();
        }
    }

    public void printB() {
    
    
        lock.lock();
        try {
    
    
            //    业务,判断 执行 通知
            while (number != 2) {
    
    
                //等待
                condition1.await();
            }
            System.out.println(Thread.currentThread().getName() + "=>BBB");
            number = 3;
            condition2.signal();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            lock.unlock();
        }
    }

    public void printC() {
    
    
        lock.lock();
        try {
    
    
            //    业务,判断 执行 通知
            while (number != 3) {
    
    
                //等待
                condition2.await();
            }
            System.out.println(Thread.currentThread().getName() + "=>BBB");
            number = 1;
            condition.signal();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            lock.unlock();
        }
    }
}

The output result meets our expectations.

image-20220301215538935

8 lock phenomenon

Lock ----> the object and class just new

8 locks are eight questions about locks. There are also four demo classes below to explain the different states of locks in various scenarios.

demo1

Two questions:

In normal mode, when two synchronized thread method calls are delayed for 1 second, will the output result be changed?

Answer: It will not affect the output order

Will the 4s delay in the synchronization method in normal mode result in an impression output?

Answer: It will not affect the output order

  • Under standard circumstances, two threads print and send text messages or make phone calls 1/send text messages 2/make phone calls
  • Send a text message with a delay of four seconds. Two threads print. Send a text message or make a phone call 1/Send a text message 2/Make a phone call.

demo code

package lock8;

import java.util.concurrent.TimeUnit;

/**
 * @projectName: JUC
 * @package: Lock8
 * @className: lock8Demo
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 *  Lock8 就是关于锁的八个问题
 * 1. 标准情况下 两个线程打印 发短信还是打电话 1/ 发短信 2/打电话
 * 2. 发短信延时四秒 两个线程打印 发短信还是打电话 1/ 发短信 2/打电话
 * @date: 2022/3/2 1:13
 * @version: 1.0
 */
public class lock8Demo {
    
    
    public static void main(String[] args) {
    
    
        phone phone = new phone();
        new Thread(() -> {
    
    
            phone.sendSms();
        }, "A").start();
        //    捕获
        try {
    
    
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        new Thread(() -> {
    
    
            phone.call();
        }, "B").start();
    }
}

class phone {
    
    
    //synchronized 锁的对象是方法调用者,
    //两个方法用的都是 phone 对象的锁,两个方法谁先拿到锁 谁执行
    public synchronized void sendSms() {
    
    
        try {
    
    
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    public synchronized void call() {
    
    
        System.out.println("打电话");
    }
}

demo2

Synchronous method execution and ordinary method execution order

Answer: There is no lock in the ordinary method, so the ordinary method first

Will the execution of two objects affect the order?

Answer: The locks of two different objects are also different. Object 1 is still waiting. The call method called by Object 2 does not need to wait, so it outputs first.

  • Now a new common method is added to ask which text message or hello should be sent first. Hello should be output first.
  • When adding two new objects, should you call or send text messages first?
package lock8;

import java.util.concurrent.TimeUnit;

/**
 * @projectName: JUC
 * @package: Lock8
 * @className: lock8Demo
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 *  Lock8 就是关于锁的八个问题
 * 3、 现在新增一个普通方法  问 先发短信还是先发hello 先输出hello
 * 4、 新增两个对象 是先打电话还是先发短信
 * @date: 2022/3/2 1:13
 * @version: 1.0
 */
public class lock8Demo2 {
    
    
    public static void main(String[] args) {
    
    
        //两个对象,现在是两个调用者所以是两个锁
        phone2 phone = new phone2();
        phone2 phone1 = new phone2();
        new Thread(() -> {
    
    
            phone.sendSms();
        }, "A").start();
        //    捕获
        try {
    
    
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        new Thread(() -> {
    
    
            phone1.call();
        }, "B").start();
    }
}

class phone2 {
    
    
    //synchronized 锁的对象是方法调用者,
    //两个方法用的都是 phone 对象的锁,两个方法谁先拿到锁 谁执行
    public synchronized void sendSms() {
    
    
        try {
    
    
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    public synchronized void call() {
    
    
        System.out.println("打电话");
    }


    //因为这里没有锁,不受锁的影响
    public void hello() {
    
    
        System.out.println("hello");
    }
}

demo3

Will calling a static synchronization method on an object change the order of execution?

Answer: No, static is a globally unique lock class template and will not change the execution and exchange order of the lock.

Will calling static synchronization methods on two objects change the order of execution?

Answer: It is the class template that cannot be statically modified, and the class template is locked instead of the class object. As long as it is an object generated by this class, no matter how many objects there are, the order will not be changed.

  • Add two static synchronization methods to an object. Only one object should print text messages or make phone calls first?
  • Add two objects and call the static synchronization method respectively. Should you print text messages or make phone calls first?
package lock8;

import java.util.concurrent.TimeUnit;

/**
 * @projectName: JUC
 * @package: Lock8
 * @className: lock8Demo
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 *  Lock8 就是关于锁的八个问题
 *  5、添加两个静态的同步方法,只有一个对象 先打印 发短信 还是打电话?
 *  6、 添加两个对象,增加两个同步方法 先打印  发短信 还是打电话?
 * @date: 2022/3/2 1:13
 * @version: 1.0
 */
public class lock8Demo3 {
    
    
    public static void main(String[] args) {
    
    

        //不管多少对象, 使用的都是底层的唯一class所以不管怎么怎么改变结果都不会变,
        // 因为synchroized锁的是class对象,static修饰的方法 类一开始就加载了,
        new Thread(() -> {
    
    
            Phone3.sendSms();
        }, "A").start();
        //    捕获
        try {
    
    
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        new Thread(() -> {
    
    
            Phone3.call();
        }, "B").start();
    }
}

//phone3是唯一的一个class
class Phone3 {
    
    
    //synchronized 锁的对象是方法调用者,
    //两个方法用的都是 phone 对象的锁,两个方法谁先拿到锁 谁执行
    // 这里 static 是静态方法 ,类一加载就有了,这个用的锁不再是 phone锁 而是class锁
    public static synchronized void sendSms() {
    
    
        try {
    
    
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    public static synchronized void call() {
    
    
        System.out.println("打电话");
    }

}

demo4

  • A static method and a common locking method. Should I print and send text messages or make phone calls first? Make the call first, because the lock is not the same thing, sync locks the class, and static locks the class.
  • There are two objects, one static method and one ordinary locking method. Should I print or send a text message first or make a phone call? Make the call first,

Answer: It’s not the same lock. Whoever executes faster will be output.

package lock8;

import java.util.concurrent.TimeUnit;

/**
 * @projectName: JUC
 * @package: Lock8
 * @className: lock8Demo
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 *  Lock8 就是关于锁的八个问题
 *  7、一个静态方法和一个普通加锁方法, 先打印 发短信 还是打电话? 先出打电话,因为锁的不是一个东西,sync锁的是类,static 是锁class
 *  8、两个对象 一个静态方法和一个普通加锁方法, 先打印 发短信 还是打电话? 先出打电话,
 * @date: 2022/3/2 1:13
 * @version: 1.0
 */
public class lock8Demo4 {
    
    
    public static void main(String[] args) {
    
    
        Phone4 phone = new Phone4();
        //不管多少对象, 使用的都是底层的唯一class所以不管怎么怎么改变结果都不会变,
        // 因为synchroized锁的是class对象,static修饰的方法 类一开始就加载了,
        new Thread(() -> {
    
    
            Phone4.sendSms();
        }, "A").start();
        //    捕获
        try {
    
    
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        new Thread(() -> {
    
    
            phone.call();
        }, "B").start();
    }
}

//phone3是唯一的一个class
class Phone4 {
    
    
    //静态同步方法是锁的 class
    public static synchronized void sendSms() {
    
    
        try {
    
    
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    //这里普通同步方法锁的是 phone
    public synchronized void call() {
    
    
        System.out.println("打电话");
    }

}

summary

We use eight different situations to understand the execution of locks in different situations:

  • Under standard circumstances, two threads print and send text messages or make phone calls 1/send text messages 2/make phone calls
  • Send a text message with a delay of four seconds. Two threads print. Send a text message or make a phone call 1/Send a text message 2/Make a phone call.
  • Now a new common method is added to ask which text message or hello should be sent first. Hello should be output first.
  • When adding two new objects, should you call or send text messages first?
  • Add two static synchronization methods to an object. Only one object should print text messages or make phone calls first?
  • Add two objects and call the static synchronization method respectively. Should you print text messages or make phone calls first?
  • A static method and a common locking method. Should I print and send text messages or make phone calls first? Make the call first, because the lock is not the same thing, sync locks the class, and static locks the class.
  • There are two objects, one static method and one ordinary locking method. Should I print or send a text message first or make a phone call? Make the call first,

You can write your own code to see the results of some of these problems. Practice will produce results, and practice will produce understanding.

The locked things are nothing more than objects and class templates

  1. The object that comes out of new is the specific object of the lock, such as a common synchronization method.
  2. The static synchronization method with static modification locks the class template, which is a globally unique object class, such as: class

Guess you like

Origin blog.csdn.net/doomwatcher/article/details/133365615