Understanding of multi-threaded synchronized locks and lock locks

Concurrency : The same object is operated by multiple threads at the same time. For
example, grab a train ticket and withdraw money at the same time.
Thread synchronization : multiple threads operate the same resource
◆Because multiple threads of the same process share the same storage space, it is convenient at the same time , It also brings the problem of access conflict. In order to ensure the correctness of the data when accessed in the method, the lock mechanism synchronized is added during the access. When a thread obtains the exclusive lock of the object, exclusive resources, other threads must wait,
after use Just release the lock. There are the following problems:
◆One thread holding the lock will cause all other threads that need this lock to hang;
◆Under multi-thread competition, locking and releasing the lock will cause more context switching and scheduling delays , Causing
performance problems;
◆If a high-priority thread waits for a low-priority thread to release the lock, it will cause priority inversion
and cause performance problems.

Synchronization code block: synchronized (Obj )()
Obj calls it a synchronization
monitorObj can be any object, but it is recommended to use shared resources as a synchronization monitor.There
is no need to specify a synchronization monitor in the synchronization method, because the synchronization method is a synchronization monitor This is the object itself, or the class [explained in reflection]
◆The execution process of the synchronization monitor
1. The first thread accesses, locks the synchronization monitor, and executes the code.
2. The second thread accesses and finds synchronization The monitor is locked and cannot be accessed.
3. After the first thread accesses, unlock the synchronization monitor.
4. The second thread accesses and finds that the synchronization monitor is not locked, then locks and accesses

There are three unsafe situations in multi-threading: the
problem of multiple people buying tickets at the train station at the same time, the problem of
two people withdrawing money at the bank at the same time,
unsafe collections, the problem
can be solved by locking

◆Buy tickets at train station

package com.lu.syn;

//不安全的买票,把buy方法加了synchronized就安全了
public class UnsafeBuyTicket {
    
    
    public static void main(String[] args) {
    
    
        BuyTicket station = new BuyTicket();

        new Thread(station,"我").start();
        new Thread(station,"你们").start();
        new Thread(station,"黄牛党").start();
    }
}

class BuyTicket implements Runnable{
    
    

    //票
    private int ticketNums = 10;
    Boolean flag = true;//外部停止方式

    @Override
    public void run() {
    
    
        //买票
        while(flag){
    
    
            try {
    
    
                buy();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }
    //synchronized 同步方法 锁的是this
    private synchronized void buy() throws InterruptedException {
    
    
        //判断是否有票
        if(ticketNums <= 0){
    
    
            flag = false;
            return;
        }
        //模拟延时
        Thread.sleep(100);
        //买票
        System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
    }
}

◆Bank withdrawal

package com.lu.syn;

//不安全的2人取钱,使用同步块解决,
//同步块可以锁任何对象
public class UnsafeBank {
    
    
    public static void main(String[] args) {
    
    
        //账户
        Account account = new Account(500, "结婚基金");

        Drawing you = new Drawing(account,50,"you");
        Drawing girlFriend = new Drawing(account, 100,"girlFriend");

        you.start();
        girlFriend.start();
    }
}

//账户
class Account{
    
    
    int money; //余额
    String name; //卡名

    public Account(int money, String name){
    
    
        this.money = money;
        this.name = name;
    }
}

//银行:模拟取款
class Drawing extends Thread{
    
    

    Account account; //账号
    int drawingMoney; //取了多少钱
    int nowMoney; // 现在有多少钱

    public Drawing(Account account, int drawingMoney, String name){
    
    
        super(name);
        this.account = account;
        this.drawingMoney = drawingMoney;
    }

    //取钱
    //synchronized默认锁的是this
    @Override
    public void run() {
    
    
        //锁的对象是变化的量,需要增删改的对象
        synchronized (account){
    
    
            //判断钱够不够
            if(account.money - drawingMoney < 0){
    
    
                System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
                return;
            }

            try {
    
    
                Thread.sleep(100);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }

            //卡内余额 = 余额 - 取的钱数
            account.money = account.money - drawingMoney;
            //手里的钱
            nowMoney = nowMoney + drawingMoney;

            System.out.println(account.name+"余额为:"+account.money);
            //Thread.currentThread().getName() = this.getName()
            System.out.println(this.getName() + "手里的钱" +nowMoney);
        }
    }
}

◆Unsafe collection

package com.lu.syn;

import java.util.ArrayList;
import java.util.List;

//线程不安全的集合。添加synchronized同步块就线程安全了
public class UnsafeList {
    
    
    public static void main(String[] args) {
    
    
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < 10000; i++) {
    
    
            new Thread(()->{
    
    
                synchronized (list){
    
    
                    list.add(Thread.currentThread().getName());
                }
            }).start();
        }

        try {
    
    
            Thread.sleep(10);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

DeadlockMultiple
threads each occupy some shared resources, and wait for the resources occupied by other threads to run,
resulting in two or more threads waiting for each other to release resources, and all stop execution. A certain synchronization block has
at the same time When "locking more than two objects", a "deadlock" problem may occur.

Four necessary conditions for deadlock:
1. Mutually exclusive conditions: A resource can only be used by one process at a time.
2. Request and hold conditions: When a process is blocked by requesting resources, it keeps the acquired resources.
3. Non-deprivation conditions: the resources already acquired by the process cannot be deprived forcibly before they are used up.
4. Cyclic waiting condition: A kind of cyclic waiting resource relationship is formed between several processes.

As long as you find a way to destroy one or more of the conditions, you can avoid deadlocks

Lock lock
Starting from JDK5.0, Java provides a more powerful thread synchronization mechanism-synchronization is achieved by explicitly defining synchronization lock objects.
Synchronization locks use Lock objects to act as
java.util.concurrent.locks.Lock interface is to control multiple threads The
ReentrantLock class, a tool for accessing shared resources, implements Lock, which has the same concurrency and memory semantics as sychronized. In the realization of thread-safe
control, ReentrantLock is more commonly used, which can display locks and release locks.

Look lock format:

class A{
    
    
	private final ReentrantLock lock = new Reen TrantLock();
		public void m(){
    
    
			lock.lock();
			try{
    
    
				//保证线程安全的代码;
			}
		finally{
    
    
			lock.unlock();
			//如果同步代码有异常,要将unlock()写 入finally语句块
		}
	}
}

The comparison of synchronized and Lock
Lock is an explicit lock (manually open and close the lock, don’t forget to close the lock) synchronized is an implicit lock, out of
scope automatically release
Lock has only code block lock, synchronized has code block lock and method lock
◆Using Lock lock, JVM will spend less time to schedule threads, and the performance is better. And has better scalability (provide more sub-categories)
◆Prioritized use order:
◆Lock> Synchronization code block (has entered the method body and allocated corresponding resources)> Synchronization method (outside the method body)

Code exercise:

import java.util.concurrent.locks.ReentrantLock;

//测试Lock锁
public class TestLock {
    
    
    public static void main(String[] args) {
    
    
        TestLock2 testLock2 = new TestLock2();

        //创建并启动3个线程
        new Thread(testLock2).start();
        new Thread(testLock2).start();
        new Thread(testLock2).start();
    }
}

class TestLock2 implements Runnable{
    
    
    int ticketNums = 10;

    //定义lock锁,要不然:多个线程同时操作同一个资源,不安全
    private final ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
    
    
        while (true){
    
    
            try {
    
    
                lock.lock();//加锁
                if (ticketNums>0){
    
    
                    try {
    
    
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                    System.out.println(ticketNums--);
                }else {
    
    
                    break;
                }
            }finally {
    
    
                lock.unlock();//解锁
            }
        }
    }
}

Guess you like

Origin blog.csdn.net/qq_42524288/article/details/105824741