美文网首页
五 异常与多线程——第三节 线程同步机制

五 异常与多线程——第三节 线程同步机制

作者: 杜艳_66c4 | 来源:发表于2022-06-05 19:07 被阅读0次

1、线程安全问题的概述

多线程访问了共享的数据,就会产生线程安全问题

2、线程安全问题的代码实现

package exception2.threadsSafe;

/**
 * created by apple on 2020/6/22,实现卖票任务
 */
public class RunnableImp implements Runnable{
    //定义多个线程共享得票源
    private int ticket = 100;

    @Override
    public void run() {
        //先判断票是否存在 。循环重复卖票。。让卖票操作重复执行
        while (true){
            if (ticket > 0){
                //提高安全问题出现的概率,让程序睡眠..会有很大的线程安全,有很多重复的票和-1 的票。
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //票存在,买票 ticket
                System.out.println(Thread.currentThread().getName()+"正在卖第" + ticket  + "票");
                ticket--;
            }
        }

    }
}
package exception2.threadsSafe;

/**
 * 模拟卖票案例
 * 创建3个线程,同时开启,对共享的票,出售
 * created by apple on 2020/6/22
 */
public class Demo01Ticket {
    public static void main(String[] args) {
        //创建Runnable接口的实现类对象
        RunnableImp  rp = new RunnableImp();
        //创建Thread类对象,构造方法中传递Runnable接口的实现类对象 。。创建的一个实现类,传到3个线程里,保证票让3个线程卖
        Thread t0 = new Thread(rp);
        Thread t1 = new Thread(rp);
        Thread t2 = new Thread(rp);
//调用start方法开启多线程
        t0.start();
        t1.start();
        t2.start();
    }
}

输出:会出现重复的票和-1 的票

Thread-0正在卖第100票
Thread-2正在卖第100票
Thread-1正在卖第100票
...
Thread-1正在卖第0票
Thread-0正在卖第-1票
卖票出现了重复的票和不存在的票

3、线程安全问题产生的原理

对共享资源的抢夺可能同时

解决线程安全问题_3种方法 :同步代码块 、同步方法,、lock锁机制

4、解决线程安全问题_1同步代码块

sychronized(锁对象){
可能会出现线程安全问题的代码,即访问了共享数据的代码
}

注意:

  • 1、同步代码块中的锁对象,可以使用任意的对象
  • 2、但是需保证多个线程使用的锁对象是同一个
  • 3、锁对象的作用: 把同步代码锁住,只让一个线程在同步代码块中执行
package exception2.sychronized;

/**
 * created by apple on 2020/6/22
 * 卖票案例出现了线程安全问题
 * 卖出了重复的票和不存在的票
 * 解决线程安全问题的第一种方案,用同步代码块
 * 格式:
 * sychronized(锁对象){
 *     可能会出现线程安全问题的代码,即访问了共享数据的代码
 * }
 * 注意:
 * 1、同步代码块中的锁对象,可以使用任意的对象
 * 2、但是需保证多个线程使用的锁对象是同一个
 * 3、锁对象的作用:
 * 把同步代码锁住,只让一个线程在同步代码块中执行
 */
public class RunnableImp implements Runnable{
    //定义多个线程共享得票源
    private int ticket = 100;
    //创建一个锁对象
    Object obj = new Object();
    @Override
    public void run() {
        //先判断票是否存在 。循环重复卖票。。让卖票操作重复执行
        while (true){
           //同步代码块,保证线程安全
            synchronized (obj){
                if (ticket > 0){
                    //提高安全问题出现的概率,让程序睡眠..会有很大的线程安全,有很多重复的票和-1 的票。
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //票存在,买票 ticket
                    System.out.println(Thread.currentThread().getName()+"正在卖第" + ticket  + "票");
                    ticket--;
                }
            }
        }

    }
}
这样就解决了线程安全问题

5、同步技术的原理

同步代码块,获取锁对象, 释放锁对象

6、解决线程安全问题_2同步方法

解决线程安全问题的第二种方案,用同步方法

  • 实现步骤:
  • 1、把访问了共享数据的代码,抽取出来,放到一个方法中
  • 2、在方法上添加sychronized修饰符
  • 定义方法的格式:
    修饰符 sychronized 返回值类型 方法名(参数列表){
    访问了共享数据的代码
    }
package exception2.sychronized02;

/**
 * created by apple on 2020/6/22
 * 卖票案例出现了线程安全问题
 * 卖出了重复的票和不存在的票
 * 解决线程安全问题的第二种方案,用同步方法
 * 实现步骤:
 * 1、把访问了共享数据的代码,抽取出来,放到一个方法中
 * 2、在方法上添加sychronized修饰符
 * 定义方法的格式:
 * 修饰符 sychronized 返回值类型 方法名(参数列表){
 *     访问了共享数据的代码
 * }
 *
 * 注意:
 * 1、通过代码块中的锁对象,可以使用任意的对象
 * 2、但是需保证多个线程使用的锁对象是同一个
 * 3、锁对象的作用:
 * 把同步代码锁住,只让一个线程在同步代码块中执行
 */
public class RunnableImp implements Runnable{
    //定义多个线程共享得票源
    private int ticket = 100;
    //创建一个锁对象
  
    @Override
    public void run() {
        //先判断票是否存在 。循环重复卖票。。让卖票操作重复执行
        while (true){
            payTicket();
        }

    }
    //定义一个同步方法.同步方法也会把方法内部的代码锁住。
    //只让一个线程执行。
    /*
    同步方法的锁对象,是线程的实现类对象。new RunnableImp()
     */
    public synchronized void payTicket(){
        if (ticket > 0){
            //提高安全问题出现的概率,让程序睡眠..会有很大的线程安全,有很多重复的票和-1 的票。
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //票存在,买票 ticket
            System.out.println(Thread.currentThread().getName()+"正在卖第" + ticket  + "票");
            ticket--;

        }
    }
}

7、静态同步方法

8、解决线程安全问题_3Lock锁

java.util.cicurrent.locks.Lock接口, 有方法获取锁 lock, unlock 释放锁

lock实现提供了比使用synchronized方法和语句可获得更广泛的锁操作

package exception2.sychronized03;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * created by apple on 2020/6/22
 * 卖票案例出现了线程安全问题
 * 卖出了重复的票和不存在的票
 * 解决线程安全问题的第三种方案,用lock锁
 * java.util.concurrent.locks.lock接口
 * 比sychronized更好用。
 *lock 接口中的 方法:
     lock():获取锁
     unlock():释放锁
 * 使用步骤:
 * 1、接口的实现类,
    java.util.concurrent.locks.Reentrantlock 实现了lock接口
    在成员位置创建一个Reentrantlock对象
 * 2、在可能出现线程安全问题的代码前,调用lock接口中的方法lock(),获取锁
 * 3、在可能出现安全问题的代码后,调用lock接口中的方法unlock(),释放锁
 */
public class RunnableImp implements Runnable{
    //定义多个线程共享得票源
    private int ticket = 100;

   //1、 在成员位置创建一个Reentrantlock对象
    Lock l = new ReentrantLock();
    @Override
    public void run() {
        //2、在可能出现线程安全问题的代码前,调用lock接口中的方法lock(),
        l.lock();
        //先判断票是否存在 。循环重复卖票。。让卖票操作重复执行
        while (true){
      //2、在可能出现线程安全问题的代码前,调用lock接口中的方法lock(),
            l.lock();
                if (ticket > 0){
                    //提高安全问题出现的概率,让程序睡眠..会有很大的线程安全,有很多重复的票和-1 的票。
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //票存在,买票 ticket
                    System.out.println(Thread.currentThread().getName()+"正在卖第" + ticket  + "票");
                    ticket--;

            }
                l.unlock();
        }

    }
}

优化下上面的写锁,把 l.unlock()放在finally中, 无论程序是否异常,都会释放锁

package exception2.sychronized03;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * created by apple on 2020/6/22
 * 卖票案例出现了线程安全问题
 * 卖出了重复的票和不存在的票
 * 解决线程安全问题的第三种方案,用lock锁
 * java.util.concurrent.locks.lock接口
 * 比sychronized更好用。
 *lock 接口中的 方法:
     lock():获取锁
     unlock():释放锁
 * 使用步骤:
 * 1、接口的实现类,
    java.util.concurrent.locks.Reentrantlock 实现了lock接口
    在成员位置创建一个Reentrantlock对象
 * 2、在可能出现线程安全问题的代码前,调用lock接口中的方法lock(),获取锁
 * 3、在可能出现安全问题的代码后,调用lock接口中的方法unlock(),释放锁
 */
public class RunnableImp implements Runnable{
    //定义多个线程共享得票源
    private int ticket = 100;

   //1、 在成员位置创建一个Reentrantlock对象
    Lock l = new ReentrantLock();
    @Override
    public void run() {
        //2、在可能出现线程安全问题的代码前,调用lock接口中的方法lock(),
        l.lock();
        //先判断票是否存在 。循环重复卖票。。让卖票操作重复执行
        while (true){
      //2、在可能出现线程安全问题的代码前,调用lock接口中的方法lock(),
            l.lock();
                if (ticket > 0){
                    //提高安全问题出现的概率,让程序睡眠..会有很大的线程安全,有很多重复的票和-1 的票。
                    try {
                        Thread.sleep(10);
            //票存在,卖票 ticket
                    System.out.println(Thread.currentThread().getName()+"正在卖第" + ticket  + "票");
                    ticket--;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
   //无论代码是否异常,都会是释放锁对象
                        l.unlock();
             }  
        }
    }
}

相关文章

  • Linux 多线程 - 线程异步与同步机制

    Linux 多线程 - 线程异步与同步机制 I. 同步机制 线程间的同步机制主要包括三个: 互斥锁:以排他的方式,...

  • 五 异常与多线程——第三节 线程同步机制

    1、线程安全问题的概述 多线程访问了共享的数据,就会产生线程安全问题 2、线程安全问题的代码实现 输出:会出现重复...

  • Python 3 多线程编程

    本文主要基于python 3.5实现多线程编程 1. 创建多线程 2. 多线程间的同步,lock机制 3. que...

  • iOS多线程--并行开发二

    接上文iOS多线程--并行开发一 4、线程同步 说到多线程就不得不提多线程中的锁机制,多线程操作过程中往往多个线程...

  • iOS面试之多线程模块

    多线程 多线程内容如下: GCD NSOperation NSThread 多线程与锁 1.GCD 同步/异步和串...

  • Android 学习流程

    1、java * 基础语法 * 面向对象 * 集合 * 多线程 * 异常 异常机制原理 自定义异常 * 输入、输出...

  • ThreadLocal源码分析

    ThreadLocal和线程同步机制相比:都是为了解决多线程中相同变量的访问冲突问题。在同步机制中,通过对象的锁机...

  • 5-线程(补充)

    Python多线程原理与实战 目的: (1)了解python线程执行原理 (2)掌握多线程编程与线程同步 (3)了...

  • 多线程

    Python多线程原理与实战 目的: (1)了解python线程执行原理 (2)掌握多线程编程与线程同步 (3)了...

  • 多线程同步与互斥机制

    1、多线程并行和并发的区别 并行:多个处理器或者多核处理器同时执行多个不同的任务。 并发:一个处理器处理多个任务。...

网友评论

      本文标题:五 异常与多线程——第三节 线程同步机制

      本文链接:https://www.haomeiwen.com/subject/imgiyrtx.html