一、线程安全问题就是指:多个线程并发访问同一个资源而发生安全性的问题,

线程安全问题都是由全局变量及静态变量引起的。

若每个线程中对全局变量、静态变量只有读操作,而无写 操作,一般来说,这个全局变量是线程安全的;

若有多个线程同时执行写操作,一般都需要考虑线程同步, 否则的话就可能影响线程安全。

问题出现:

public class ThreadSafe implements Runnable {
private int ticket = 100; /**
* 执行买票
*/
public void run() {
while (true){
if(ticket>0){
//提高线程安全问题出现概率,让他睡眠
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" 正在卖第:"+ticket+"票");
ticket--;
}
}
}} public class ThreadSafeTest {
public static void main(String[] args) {
//创建target目标实现类
ThreadSafe threadSafe = new ThreadSafe();
//开启三个线程窗口,必须三个线程实例对象共享一个目标对象,才能保证票数就三百张
Thread th1 = new Thread(threadSafe,"窗口一");
Thread th2 = new Thread(threadSafe,"窗口二");
Thread th3 = new Thread(threadSafe,"窗口三");
th1.start();
th2.start();
th3.start();
}
}

二、窗口1线程进入操作的时候,窗口2和窗口3线程只能在外等着,窗口1操作结束,窗口1和窗口2和窗口3才有机会进入代码 去执行。也就是说在某个线程修改共享资源的时候,其他线程不能修改该资源,等待修改完毕同步之后,才能去抢夺CPU 资源,完成对应的操作,保证了数据的同步性,解决了线程不安全的现象

三、引用同步机制解决线程安全问题

1. 同步代码块。 2. 同步方法。 3. 锁机制

  A、同步代码块
格式:
synchronized(同步锁){      
需要同步操作的代码
} 同步锁: 对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁.
1. 锁对象 可以是任意类型。
2. 多个线程对象 要使用同一把锁
3. 锁对象的作用:把同步代码块锁住,只允许一个线程在同步代码块上执行 测试: public class ThreadSafe implements Runnable {
private int ticket = 100;
Object obj = new Object();
/**
* 执行买票
*/
public void run() {
while (true){
synchronized (obj){
if(ticket>0){
//提高线程安全问题出现概率,让他睡眠
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" 正在卖第:"+ticket+"票");
ticket--;
}
}
}
}
} 3. Lock(锁)
Lock锁也称同步锁,加锁与释放锁方法化了,如下:
public void lock() :加同步锁。
public void unlock() :释放同步锁
使用步骤:
1.在成员变量位置创建一个ReentrantLock()对象;
2.在可能出现安全问题的代码前调用Lock接口中的方法lock()
3.在可能出现安全问题的代码后调用Lock接口中的方法unlock() public class ThreadSafe1 implements Runnable {
private int ticket = 100;
Lock lock = new ReentrantLock();
/**
* 执行买票
*/
public void run() {
while (true){
lock.lock();
if(ticket>0){
//提高线程安全问题出现概率,让他睡眠
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" 正在卖第:"+ticket+"票");
ticket--;
}
lock.unlock();
}
}
}

JAVA基础之多线程三期--线程安全问题的更多相关文章

  1. Java基础之多线程篇(线程创建与终止、互斥、通信、本地变量)

    线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public ...

  2. java学习笔记 --- 多线程(线程安全问题——同步代码块)

    1.导致出现安全问题的原因: A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 2.解决线程安全问题方法: 同步代码块: synchronized(对象){ 需要同步的代码; ...

  3. Java学习之多线程(线程安全问题及线程同步)

    一.线程安全问题产生前提:1.多线程操作共享数据2.线程任务中有多条代码 class Ticket implements Runnable { //2.共享数据 private int num = 1 ...

  4. 黑马程序员——JAVA基础之多线程的线程间通讯等

    ------- android培训.java培训.期待与您交流! ---------- 线程间通讯: 其实就是多个线程在操作同一个资源,但是动作不同. wait(); 在其他线程调用此对象的notif ...

  5. Java基础学习——多线程之线程池

    1.线程池介绍     线程池是一种线程使用模式.线程由于具有空闲(eg:等待返回值)和繁忙这种不同状态,当数量过多时其创建.销毁.调度等都会带来开销.线程池维护了多个线程,当分配可并发执行的任务时, ...

  6. Java基础技术多线程与并发面试【笔记】

    Java基础技术多线程与并发 什么是线程死锁? ​死锁是指两个或两个以上的进程(线程)在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去,我们就可以称 ...

  7. Java学习笔记-多线程-创建线程的方式

    创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...

  8. 处理java多线程时线程安全问题 - ThreadLocal和Synchronized

    多线程在自动化测试中用的不多,也就是说我们用单线程可以完成大部分的自动化测试脚本. 主要有两个原因,首先是因为自动化测试首要考虑的是脚本的稳定性,所以一般会牺牲效率以保证脚本稳定,其次是由于局限于我们 ...

  9. Java基础之多线程

    1.进程和线程: 进程:正在进行的程序.每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元. 线程:进程内部的一条执行路径或者一个控制单元. 两者的区别: 一个进程至少有一个线程 ...

  10. 黑马程序员——【Java基础】——多线程

    ---------- android培训.java培训.期待与您交流! ---------- 一.概述 (一)进程 正在执行中的程序,每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控 ...

随机推荐

  1. 2025-01-15:执行操作可获得的最大总奖励 Ⅰ。用go语言,给定一个整数数组 rewardValues,其中包含 n 个代表奖励值的数字。 你开始时的总奖励 x 为 0,并且所有下标都是未标记状

    2025-01-15:执行操作可获得的最大总奖励 Ⅰ.用go语言,给定一个整数数组 rewardValues,其中包含 n 个代表奖励值的数字. 你开始时的总奖励 x 为 0,并且所有下标都是未标记状 ...

  2. 一文搞懂企业架构与DDD融合

    大家好,我是汤师爷~ 今天聊聊企业架构与DDD如何进行融合. 企业架构TOGAF 什么是企业架构TOGAF? TOGAF(The Open Group Architecture Framework)是 ...

  3. 一文搞懂 结构伪类 :nth-child && :nth-of-typ

    结构伪类 从使用结构伪类的选择器开始 往上一层父辈开始筛选 从使用结构伪类的选择器开始 往上一层父辈开始筛选 从使用结构伪类的选择器开始 往上一层父辈开始筛选 不是从左往右选择 不是先父辈后筛选子类 ...

  4. 在SOUI中将自定义配置信息写到布局文件中

    SOUI的布局XML文件保存布局必须的信息.特定场合中,用户可能会需要在布局中指定业务需要处理的属性. 比如启程输入法的皮肤.有的皮肤支持高分屏,有的皮肤不支持.对于这个场景,比较理想的方案是直接在皮 ...

  5. RocketMQ实战—8.营销系统业务和方案介绍

    大纲 1.电商核心交易场景的业务流程 2.电商支付后履约场景的业务流程 3.电商营销场景的业务说明 4.电商促销活动的Push推送 5.会员与推送的数据库表结构 6.营销系统的数据库表结构 7.营销系 ...

  6. getDerivedStateFromProps 详解

    getDerivedStateFromProps 是 React 生命周期中的一个静态方法,主要用于在组件接收到新的 props 时更新 state.这个方法在组件的初始渲染和后续的每次更新(即每次接 ...

  7. DM SQL关联列 like 优化案例

    1.1.sql优化背景 达梦一哥们找我优化条SQL,反馈在DM8数据库执行时间很慢出不来结果, 监控工具显示这条SQL的执行时间需要20多万毫秒,安排. 1.2.慢sql和执行时间 select a. ...

  8. Python 潮流周刊#89:Python 3.14 的新型解释器!(摘要)

    本周刊由 Python猫 出品,精心筛选国内外的 250+ 信息源,为你挑选最值得分享的文章.教程.开源项目.软件工具.播客和视频.热门话题等内容.愿景:帮助所有读者精进 Python 技术,并增长职 ...

  9. Kettle - 简介

    ETL简介 Kettle简介 transformation 和 job的区别 Kettle 的核心组件 Kettle 特点 Kettle 的目录说明 Kettle 的文件说明 ETL简介 ETL,Ex ...

  10. Scala样例类及底层实现伴生对象

    package com.wyh.day01 /** * 样例类的使用 * 1.使用case修饰类 * 2.不需要写构造方法,getter,setter方法,toString方法 * 3.直接通过对象名 ...