12. Thread synchronization mechanism

Thread synchronization (multiple threads operate on the same resource) synchronized

Thread synchronization formation conditions: queue + lock

keyword: synchronized

Concurrency

  • Concurrency: the same object is manipulated by multiple threads at the same time

  • Thread synchronization is actually a waiting mechanism. Multiple threads that need to access this object at the same time enter the waiting pool of this object to form a queue

    Waiting for the previous thread to be used up, the next thread is in use

  • In order to ensure the correctness of data when it is accessed in the method, a lock

  • When a thread obtains an exclusive lock on an object, it monopolizes the resource, and other threads must wait to release the lock after using it. There are the following problems:

    • Holding a lock by one thread can cause all other threads that need the lock to hang (decreased performance)
    • Under multi-threaded competition, locking and releasing locks 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

Synchronized methods and synchronized blocks

  • Synchronized method: public synchronized void method(){}

  • Synchronized block: synchronized (Obj){}

  • The default lock for synchronized is this

  • The object of the lock is the amount of change, that is, the object that needs to be added, deleted, or modified (which class of object will change, which object will be locked)

  • The synchronized method controls access to "objects", each object has a corresponding lock,

    Each synchronized method must acquire the lock of the object calling the method to execute, otherwise the thread will block,

    Once the method is executed, the lock is exclusively used, and the lock is not released until the method returns, and the blocked thread can obtain the lock and continue to execute

  • defect:

    • Declaring a large method as synchronized will affect efficiency
    • Only the content that needs to be modified in the method needs to be locked. Too many locks are a waste of resources.

Synchronized processing of ticket purchases

package com.syn;

// 不安全的买票
// 线程不安全。有负数
public class UnsafeBuyTicket {
    public static void main(String[] args) {
        BuyTicket buyTicket = new BuyTicket();

        new Thread(buyTicket,"苦逼的我").start();
        new Thread(buyTicket,"牛逼的你们").start();
        new Thread(buyTicket,"可恶的黄牛党").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();
            }
        }
    }

    private synchronized void buy() throws InterruptedException {
        // 判断是否有票
        if (ticketNums<0){
            flag = false;
            return;
        }
        // 模拟延时
        Thread.sleep(100);
        // 买票
        System.out.println(Thread.currentThread().getName() + "拿到" + ticketNums--);
    }
}

Synchronized processing of bank withdrawals

package com.syn;

// 不安全的取钱
// 俩个人去银行取钱,账户
public class UnsafeBank {
    public static void main(String[] args) {
        Account account = new Account(1000,"结婚基金");

        Drawing you = new Drawing(account,50,"你");
        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;
            }

            // sleep 可以放大问题的发生性
            try {
                Thread.sleep(1000);
            } 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);

        }
    }
}

Thread-unsafe collections

package com.syn;

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

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(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(list.size());
    }
}

Test a collection of JUC-safe types

package com.syn;

import java.util.concurrent.CopyOnWriteArrayList;

// 测试JUC安全类型的集合
public class TestJUC {
    public static void main(String[] args) {
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();

        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                list.add(Thread.currentThread().getName());
            }).start();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

Guess you like

Origin blog.csdn.net/weixin_56121715/article/details/123780964