线程安全_hehe.employment.6.2

6.8 线程安全问题概述

  • 图示:
    在这里插入图片描述

6.9线程安全问题的代码实现

  • 示例:
package com.xww.demo05;

public class RunnableImpl implements Runnable{
    private int ticket = 100;
    @Override
    public void run() {
        //使用死循环,让卖票操作重复执行
        while(true){
            //先判断票是否存在
            if(ticket>0){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+":"+ticket);
                ticket--;
            }
        }
    }
}

package com.xww.demo05;
/*
    模拟卖票
    创建3个进程,同时开启,对共享票进行出售
 */
public class demoTick {
    public static void main(String[] args) {
        //创建Runnable接口的实现类对象
        RunnableImpl run = new RunnableImpl();
        //创建Thread类对象,构造方法中传递Runnable接口的实现类对象
        Thread t0 = new Thread(run);
        Thread t1 = new Thread(run);
        Thread t2 = new Thread(run);
        //调用start方法开启多线程
        t0.start();
        t1.start();
        t2.start();
    }
}

6.10 线程安全问题产生的原理

  • 图示:

在这里插入图片描述
6.11 线程安全问题_同步代码块

  • 同步代码块synchronized 关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问
  • 格式:
synchronized(锁对象){
	可能出现线程安全问题的代码(访问了共享数据的代码);
}
  • notes:
    • 通过代码块中的锁对象,可以使用任意的对象
    • 但是必须保证多个线程使用的锁对象是同一个
    • 锁对象的作用:把同步代码块锁住,只让一个线程在同步代码块中执行。
  • 示例:
package com.xww.demo05;

public class RunnableImpl implements Runnable{
    //定义一个多个线程共享的资源
    private int ticket = 100;

    //创建一个锁对象
    Object obj = new Object();
    //设置线程任务
    @Override
    public void run() {
        //使用死循环,让卖票操作重复执行
        while(true){
            synchronized (obj){
                //先判断票是否存在
                if(ticket>0){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+":"+ticket);
                    ticket--;
                }
            }
        }
    }
}

6.12 同步技术的原理

  • 图示:

在这里插入图片描述
6.13 解决线程安全问题_同步方法

  • 同步方法 :使用synchronized修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外 等着。
  • 同步方法的对象:就是实现类对象 new RunnableImpl,也就是this
  • 格式:定义方法的格式
修饰符 synchronized 返回值类型 方法名(参数列表){
	可能会产生线程安全问题的代码(访问量共享数据的代码);
}
  • 使用步骤:
    • 把访问了共享数据的代码抽取出来,放到一个方法中;
    • 在方法中添加synchronized修饰符。
  • 示例:
package com.xww.demo05;

public class RunnableImpl implements Runnable{
    //定义一个多个线程共享的资源
    private int ticket = 100;

    //设置线程任务
    @Override
    public void run() {
        //使用死循环,让卖票操作重复执行
        while(true){
            payTicket();
        }
    }
    //定义一个同步方法
    public  synchronized void payTicket(){
        //先判断票是否存在
        if(ticket>0){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+":"+ticket);
            ticket--;
        }
    }
}

6.14 解决线程安全问题_静态同步方法

  • 静态的同步方法的锁对象:
    • 不能是this,因为this是创建对象之后产生的,静态方法优先于对象;
    • 是本类的Class属性–>Class文件对象(反射)。
  • 示例:
package com.xww.demo05;

public class RunnableImpl implements Runnable{
    //定义一个多个线程共享的资源
    private static int ticket = 100;

    //设置线程任务
    @Override
    public void run() {
        //使用死循环,让卖票操作重复执行
        while(true){
            payTicket();
        }
    }
    //定义一个静态同步方法
    public  static synchronized void payTicket(){
        //先判断票是否存在
        if(ticket>0){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+":"+ticket);
            ticket--;
        }
    }
}

6.15 解决线程安全问题_Lock 锁

  • java.util.concurrent.locks.Lock 机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作,同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象。
  • Lock锁 也称同步锁,加锁与释放锁方法化了。
  • Lock接口中的方法如下:
    • public void lock() :加同步锁。
    • public void unlock() :释放同步锁。
  • java.util.concurrent.locks.ReentrantLock implements Lock接口
  • 使用步骤:
    • 在成员位置创建一个ReentrantLock对象
    • 在可能会出现安全问题的代码调用Lock接口中的方法lock获取锁;
    • 在可能会出现安全问题的代码调用Lock接口中的方法unlock释放锁。
  • 示例:
package com.xww.demo05;

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

public class RunnableImpl implements Runnable{
    //定义一个多个线程共享的资源
    private  int ticket = 100;

    //1.在成员位置创建一个ReentrantLock对象
    Lock l = new ReentrantLock();
    //设置线程任务
    @Override
    public void run() {
        //使用死循环,让卖票操作重复执行
        while(true){
            //2.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁;
            //先判断票是否存在
            if(ticket>0){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+":"+ticket);
                ticket--;
            }
            //3.在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放锁;
            l.unlock();
        }
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值