JAVA基础之多线程三期--线程安全问题
一、线程安全问题就是指:多个线程并发访问同一个资源而发生安全性的问题,
线程安全问题都是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,而无写 操作,一般来说,这个全局变量是线程安全的;
若有多个线程同时执行写操作,一般都需要考虑线程同步, 否则的话就可能影响线程安全。
问题出现:
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基础之多线程三期--线程安全问题的更多相关文章
- Java基础之多线程篇(线程创建与终止、互斥、通信、本地变量)
线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public ...
- java学习笔记 --- 多线程(线程安全问题——同步代码块)
1.导致出现安全问题的原因: A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 2.解决线程安全问题方法: 同步代码块: synchronized(对象){ 需要同步的代码; ...
- Java学习之多线程(线程安全问题及线程同步)
一.线程安全问题产生前提:1.多线程操作共享数据2.线程任务中有多条代码 class Ticket implements Runnable { //2.共享数据 private int num = 1 ...
- 黑马程序员——JAVA基础之多线程的线程间通讯等
------- android培训.java培训.期待与您交流! ---------- 线程间通讯: 其实就是多个线程在操作同一个资源,但是动作不同. wait(); 在其他线程调用此对象的notif ...
- Java基础学习——多线程之线程池
1.线程池介绍 线程池是一种线程使用模式.线程由于具有空闲(eg:等待返回值)和繁忙这种不同状态,当数量过多时其创建.销毁.调度等都会带来开销.线程池维护了多个线程,当分配可并发执行的任务时, ...
- Java基础技术多线程与并发面试【笔记】
Java基础技术多线程与并发 什么是线程死锁? 死锁是指两个或两个以上的进程(线程)在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去,我们就可以称 ...
- Java学习笔记-多线程-创建线程的方式
创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...
- 处理java多线程时线程安全问题 - ThreadLocal和Synchronized
多线程在自动化测试中用的不多,也就是说我们用单线程可以完成大部分的自动化测试脚本. 主要有两个原因,首先是因为自动化测试首要考虑的是脚本的稳定性,所以一般会牺牲效率以保证脚本稳定,其次是由于局限于我们 ...
- Java基础之多线程
1.进程和线程: 进程:正在进行的程序.每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元. 线程:进程内部的一条执行路径或者一个控制单元. 两者的区别: 一个进程至少有一个线程 ...
- 黑马程序员——【Java基础】——多线程
---------- android培训.java培训.期待与您交流! ---------- 一.概述 (一)进程 正在执行中的程序,每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控 ...
随机推荐
- 利用坦克PWA3快速为应用配置域名:以Gogs为例
全文概述 本文介绍了如何利用坦克PWA3平台快速为Gogs应用配置域名的过程.随着互联网技术的发展,自托管Git服务变得越来越受欢迎,其中Gogs凭借其轻量级和易于安装的特点受到众多开发者的青睐.为提 ...
- Kotlin:【定义类】field、计算属性、防态竞争条件
- 接口(interface):实例化时要覆盖所有抽象方法,否则仍为抽象类
概述 /* * 接口的使用 * 1.接口使用interface来定义 * 2.Java中,接口和类是并列的两个结构 * 3.如何定义接口:定义接口中的成员 * * 3.1 JDK7及以前:只能定义全局 ...
- Breakout pg walkthrough Intermediate
nmap ┌──(root㉿kali)-[~/lab] └─# nmap -p- -A 192.168.192.182 Starting Nmap 7.94SVN ( https://nmap.org ...
- mysl 修改数据存储位置后服务启动后停止
在 Windows 系统中安装完 mysql 后,如果是生产用的机器,通常会修改数据存储位置.基本步骤: 1. 停止 mysql 服务: 2. 修改 my.ini 文件中的 datadir=" ...
- redis如何设置密码
密码设置 这里简单介绍一下redis如何设置密码redis密码设置有两种方式,一种需要重启redis服务,一种不需要重启redis服务. 首先,介绍一下需要重启redis服务的设置方式即找到redis ...
- Atcoder ABC387F Count Arrays 题解 [ 绿 ] [ 基环树 ] [ 树形 dp ] [ 前缀和优化 ]
Count Arrays:一眼秒的计数题. 思路 显然,把小于等于的条件化为大的向小的连单向边,每个数的入度都是 \(1\),就会形成一个基环树森林. 那么考虑这个环上能填什么数.因为所有数都小于等于 ...
- Linux驱动---设备驱动模型
目录 一.简介 二.驱动模型 2.1.总线 2.2.设备 2.3.驱动 三.设备树 3.1.设备树简介 3.2.设备树格式 3.3.节点格式 3.4.节点属性 四.设备树API函数 4.1获取设备节点 ...
- Drasi Sources SDK
什么是Drasi数据源(Source)? Source提供了与系统的连接,Drasi 可以将这些系统视为变化源.source 在 Drasi 中执行三个重要功能: 处理源系统生成的更改日志/源,并将这 ...
- Hbuilder使用快捷键
Hbuilder的使用 1.Hbuilder基本操作设置基本外观文字大小,申请账号.2.Hbuilder快捷键- 新建菜单: ctrl + N- 新建: ctrl + N- 关闭: ctrl ...