Compartilhamento de tecnologia

Segurança de thread (2) O princípio de implementação subjacente de sincronização, atualização de bloqueio e estrutura de memória de objeto

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

1. Uso básico

  • Suponha que exista tal cenário:20 usuários pegam 10 ingressos juntos

1.1 Implementação de código sem bloqueio

public class TicketDemo {
   

    // 票总数
    private int ticketNum = 10;

    /**
     * 抢票
     */
    public void getTicket() {
   
        if (ticketNum <= 0) {
   
            return;
        }
        System.out.println(Thread.currentThread().getName() + " 抢到一张票,剩余:" + ticketNum);
        // 非原子性操作
        ticketNum--;
    }

    /**
     * 测试:20个人抢一张票
     */
    public static void main(String[] args) {
   
        TicketDemo ticketDemo = new TicketDemo();
        for (int i = 0; i < 20; i++) {
   
            new Thread(ticketDemo::getTicket).start();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

Resultados do:

Você pode ver que aparece problema de sobrevenda , há 10 ingressos no total. Quando 20 threads compram ingressos juntos, 11 pessoas parecem ter adquirido os ingressos. Isso ocorre porque se ambos os threads passarem na verificação if ao mesmo tempo.

Portanto, precisamos bloquear a operação do ticket para garantir que apenas um thread possa verificar e operar a dedução do ticket ao mesmo tempo.

1.2 Implementação do código de bloqueio

public class TicketDemo {
   

    // 锁
    private static Object lock = new Object();

    // 票总数
    private int ticketNum = 10;

    /**
     * 抢票
     */
    public void getTicket() {
   
        synchronized (lock) {
   
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16