JAVA多线程之间实现同步+多线程并发同步解决方案

一、什么是线程安全问题 

为什么有线程安全问题?

       当多个线程同时共享同一个全局变量或静态变量,做写的操作(修改变量值)时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作时不会发生数据冲突问题。


案例:需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果。
/**
 * 需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果。
 * Created by yz on 2018/04/01.
 */
public class ThreadDemo {
    public static void main(String[] args) {
        // t1 t2同时共享同一变量trainCount
        ThreadTrain threadTrain = new ThreadTrain();
        Thread t1 = new Thread(threadTrain, "窗口1");
        Thread t2 = new Thread(threadTrain, "窗口2");
        t1.start();
        t2.start();
    }
}

// 售票窗口
class ThreadTrain implements Runnable{
    // 总共有100张火车票
    private int trainCount = 100;
    public void run() {
        while (trainCount > 0){
            try {
                // 休眠50秒
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 出售火车票
            sale();
        }
    }

    // 卖票方法
    public void sale(){
        System.out.println(Thread.currentThread().getName()+",出售第"+(100-trainCount+1)+"张票");
        trainCount--;
    }
}
运行结果:

原因解析:

卖票方法加判断,不能百分百解决问题

// 卖票方法
public void sale(){
    if(trainCount > 0){
        System.out.println(Thread.currentThread().getName()+",出售第"+(100-trainCount+1)+"张票");
        trainCount--;
    }
}

原因解析:

多个线程共享同一个局部变量,会发生线程安全问题吗?不会

线程安全问题,有哪些解决办法?

解决办法:
synchronized    --- 自动锁
lock --- jdk1.5并发包 --- 手动锁

线程之间如何同步?
同步是保证数据原子性,原子性就是数据不能受到其他线程干扰。

二、使用同步代码块解决线程安全问题 

什么地方需要考虑加锁?
考虑在真正产生共享同一个全局变量的时候使用,不要用synchronized去包裹整个代码。

// 卖票方法
public void sale(){
    // 同步代码块 synchronized 包裹需要线程安全的问题。
    synchronized (object){
        if(trainCount > 0){
            System.out.println(Thread.currentThread().getName()+",出售第"+(100-trainCount+1)+"张票");
            trainCount--;
        }
    }
}
什么是同步代码块?
答:就是将可能会发生线程安全问题的代码,给包裹起来
synchronized(对象){  // 这个对象可以为任意对象  
可能会发生线程冲突的问题
}

对象如同锁,持有锁的线程可以在同步块中执行,没持有锁的线程,即使获取cup的执行权,也进不去。

使用synchronized必须有一些条件:
1.必须要有两个或者两个以上的线程需要发生同步。
2.多个线程想同步,必须使用同一把锁

3.保证只有一个线程进行执行

synchronized原理:
1.首先有一个线程已经拿到了锁,其他线程已经有cup执行权,一直排队,等待释放锁。
2.锁是在什么时候释放?代码执行完毕或者程序抛出异常都会被释放掉。
3.锁已经被释放掉的话,其他线程开始进行抢锁(资源竞争),谁抢到谁进入同步中去,其他线程继续等待。

好处:解决了多线程的安全问题
弊端:效率非常低,多个线程需要判断锁,比较消耗资源,抢锁的资源。

什么是线程之间同步?
同步是保证多个线程之间共享同一个全局变量数据安全问题,保证数据原子性。

synchronized 只能有一个线程进行执行(就像厕所只有一个坑,好多人等着上厕所,谁进入厕所谁上锁,其他人在外等待),这个线程不释放锁的话,其他线程就一直等,就会产生死锁问题。


三、同步函数使用、this锁 

同步函数
什么是同步函数?
答:在方法上加上synchronized进行修饰 称为同步函数。

// 卖票方法 
public synchronized void sale(){
    if(trainCount > 0){
        System.out.println(Thread.currentThread().getName()+",出售第"+(100-trainCount+1)+"张票");
        trainCount--;
    }
}
同步函数使用的是什么锁?this锁
怎么证明同步函数使用的是this锁?
两个线程之间实现同步,一个线程使用this锁同步代码块,一个线程使用同步函数,这两个线程如果同步,说明同步函数使用的是this锁。
/**
 * 需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果。
 * Created by yz on 2018/04/01.
 */
public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        // t1 t2同时共享同一变量trainCount
        ThreadTrain threadTrain = new ThreadTrain()

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值