线程的并发问题及解决方案

线程的并发问题,先看两个例子
例1、经典的卖票问题,火车站售票厅,代售点,12306都在销售。比如2月14号当天北京西到广州南总共剩余1000张票(0号到999号票)。现在模拟三个渠道销售火车票。

public class TestThreadProplem {
    private static int tickets = 100;

    public static void main(String[] args) {
        new Thread(() -> saleTicket(), "售票厅").start();
        new Thread(() -> saleTicket(), "代售点").start();
        new Thread(() -> saleTicket(), "12306").start();
    }

    private static void saleTicket() {
        while (tickets > 0) {
            // 模拟卖出了一张票
            System.out.println(Thread.currentThread().getName() + "卖出了" + tickets);
            // 总票数减1
            tickets--;
        }
    }
运行结果;出现了多渠道卖了同一张票的问题。比如92号票
Connected to the target VM, address: '127.0.0.1:52198', transport: 'socket'
售票厅卖出了100
售票厅卖出了99
售票厅卖出了98
售票厅卖出了97
售票厅卖出了96
售票厅卖出了95
代售点卖出了97
代售点卖出了93
售票厅卖出了94
代售点卖出了92
售票厅卖出了91
12306卖出了92

例2、常用的日期格式化工具SimpleDateFormat

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class TestThreadProplem2 {
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    private static String strDate = "2020-12-03";

    public static void main(String[] args) {
        new Thread(() -> formatCurDateToString(), "thread1").start();
        new Thread(() -> formatCurDateToString(), "thread2").start();
        new Thread(() -> formatCurDateToString(), "thread3").start();
    }

    private static void formatCurDateToString() {
        try {
            Date date = sdf.parse(strDate);
            System.out.println(Thread.currentThread().getName() + "格式化当前日期" + sdf.format(date));
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}
多运行几遍出现如下结果
thread3格式化当前日期2020-12-03
thread1格式化当前日期2022-08-03
thread2格式化当前日期2022-08-03

出现问题的原因是多线程对共享数据的操作导致的。
因为数据时对线程共享的,某一时刻,某几个线程可能同时访问到共享数据的结果是一样的,导致各自都对共享数据做了操作。导致出现了不一致的情况。

2、线程并发问题如何解决?
问题出现在某一时刻共享数据访问操作上,那解决方案就有两种。
解决方案1:对共享数据的操作采用同步机制。
也就是访问共享数据要一个一个排队进行访问。想到排队那就加锁,第一个线程访问或操作的时候,加上锁,自己访问完了,再释放锁,下一个进程才能进来访问或操作。所以第一种解决方案是加锁。

例1:卖票加锁同步改造待更新...

解决方案2::就是不共享了,各用各的。
比如例二中日期格式化工具由于共享出现了问题。那就不共享了每个线程都用自己的。比如给每个线程重新new一个SimpleDateFormat。这种可以使用ThreadLocal保存每个线程独有的东西,保证各个线程各用各的,互不影响。

例2:日期格式化工具让每个线程都使用自己的,改造待更新......
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值