解决线程不安全的方式(Java)
一、同步代码块
package com.synchronized1; // 买票示例
// 使用同步代码块解决线程安全问题
public class TicketRunnableImp implements Runnable {
private int ticket = 100;
Object o=new Object();
@Override
public void run() {
while (true) {
synchronized (o){
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "-->正在售第"+ticket+"张票!");
ticket--;
}
}
}
}
}
实现原理:使用了一个锁对象.这个锁对象也叫同步锁,对象锁,对象监视器。先进入同步代码块的线程会先获取到锁对象,其他线程不能进入代码块,只有先进入同步代码块的线程
执行完毕同步代码块释放锁对象后,其他线程才有机会获取到锁对象进入同步代码块。也就是每次只有一个线程进入到同步代码块执行逻辑。
优点:实现了线程安全
缺点:程序不停的判断锁,获取锁,释放锁,效率会降低
二、同步方法
package com.synchronized2; // 买票示例
// 使用同步方法解决线程安全问题
public class TicketRunnableImp implements Runnable {
private int ticket = 100;
Object o = new Object(); @Override
public void run() {
while (true) {
func();
}
}
// 同步方法的锁对象是调用者对象(Runnable对象)
public synchronized void func(){
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "-->正在售第" + ticket + "张票!");
ticket--;
}
}
}
实现原理:和同步代码块实现原理基本一致,同步方法中的锁对象是线程实现类的对象。
三、静态方法
package com.staticSyn; // 买票示例
// 使用同步方法解决线程安全问题
public class TicketRunnableImp implements Runnable {
private static int ticket = 100;
Object o = new Object(); @Override
public void run() {
while (true) {
func();
}
}
// 静态方法的锁对象是本类的class属性
public synchronized static void func(){
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "-->正在售第" + ticket + "张票!");
ticket--;
}
}
}
四、Lock锁
方式一
package com.lock1; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; // 买票示例
// 使用同步代码块解决线程安全问题
public class TicketRunnableImp implements Runnable {
private int ticket = 100;
Object o = new Object();
Lock lock=new ReentrantLock();
@Override
public void run() {
while (true) {
lock.lock();
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "-->正在售第" + ticket + "张票!");
ticket--;
}
lock.unlock();
}
}
}
方式二
package com.lock2; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; // 买票示例
// 使用同步代码块解决线程安全问题
public class TicketRunnableImp implements Runnable {
private int ticket = 100;
Object o = new Object();
Lock lock = new ReentrantLock(); @Override
public void run() {
while (true) {
lock.lock();
try {
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "-->正在售第" + ticket + "张票!");
ticket--;
}
} catch (Exception e) {
System.out.println(e);
} finally {
lock.unlock();
}
}
}
}
五、上述几种方式的测试类
package com.lock2;
public class DemoTicket {
public static void main(String[] args) {
TicketRunnableImp t=new TicketRunnableImp();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
Thread t3=new Thread(t);
t1.start();
t2.start();
t3.start();
}
}
解决线程不安全的方式(Java)的更多相关文章
- java 22 - 13 多线程之解决线程安全问题的实现方式2
上一章说了,解决线程安全问题的实现方式1是使用同步代码块 同时也知道了,同步代码块的锁对象是任意对象:(Object obj ; Demo d;)这些都行 那么,现在来说解决线程安全问题的实现方式2 ...
- java 22 - 12 多线程之解决线程安全问题的实现方式1
从上一章知道了多线程存在着线程安全问题,那么,如何解决线程安全问题呢? 导致出现问题的原因: A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 上一章的程序,上面那3条都具备, ...
- Java并发编程:Java创建线程的三种方式
目录 引言 创建线程的三种方式 一.继承Thread类 二.实现Runnable接口 三.使用Callable和Future创建线程 三种方式的对比 引言 在日常开发工作中,多线程开发可以说是必备技能 ...
- Java之解决线程安全问题的方式三:Lock锁
import java.util.concurrent.locks.ReentrantLock; /** * 解决线程安全问题的方式三:Lock锁 --- JDK5.0新增 * * 1. 面试题:sy ...
- java线程安全问题以及使用synchronized解决线程安全问题的几种方式
一.线程安全问题 1.产生原因 我们使用java多线程的时候,最让我们头疼的莫过于多线程引起的线程安全问题,那么线程安全问题到底是如何产生的呢?究其本质,是因为多条线程操作同一数据的过程中,破坏了数据 ...
- java——多线程的实现方式、三种办法解决线程赛跑、多线程数据同步(synchronized)、死锁
多线程的实现方式:demo1.demo2 demo1:继承Thread类,重写run()方法 package thread_test; public class ThreadDemo1 extends ...
- Lock锁方式解决线程安全问题
在JDK5.0之后新增加了一种更强大的线程同步机制---通过显示定义同步锁来实现线程同步解决线程安全问题.同步锁使用Lock对象充当. java.util.concurrent.locks.lock接 ...
- java并发之如何解决线程安全问题
并发(concurrency)一个并不陌生的词,简单来说,就是cpu在同一时刻执行多个任务. 而Java并发则由多线程实现的. 在jvm的世界里,线程就像不相干的平行空间,串行在虚拟机中.(当然这是比 ...
- Java实现线程的三种方式和区别
Java实现线程的三种方式和区别 Java实现线程的三种方式: 继承Thread 实现Runnable接口 实现Callable接口 区别: 第一种方式继承Thread就不能继承其他类了,后面两种可以 ...
- Java基础_通过模拟售票情景解决线程不安全问题
用代码来模拟铁路售票系统,实现通过四个售票点发售某日某次列车的100张车票,一个售票点用一个线程表示 第一种方法:通过继承Thread类的方法创建线程 package com.Gary1; publi ...
随机推荐
- 【HZERO】数据导入
#数据导入 ##文档整理 通用导入客户端 https://open.hand-china.com/hzero-docs/v1.3/zh/docs/service/import/import/ 开放平台 ...
- C# 实用第三方库
C# 实用第三方库 Autofac 依赖注入IOC框架 NuGet安装:Autofac.Autofac.Extras.DynamicProxy AutoMapper 对象映射 Mapster 对象映射 ...
- SpringBoot AOP 记录操作日志、异常日志
使用SpringBoot AOP 记录操作日志.异常日志 我们在做项目时经常需要对一些重要功能操作记录日志,方便以后跟踪是谁在操作此功能.在操作某些功能时也有可能会发生异常,但是每次发生异常要定位原因 ...
- C# 序列化器
理论知识: 序列化是指将对象转换成字节流,从而存储对象或将对象传输到内存.数据库或文件的过程. 它的主要用途是保存对象的状态,以便能够在需要时重新创建对象. 反向过程称为"反序列化" ...
- Elasticsearch 索引与文档的常用操作总结一
本文为博主原创,未经允许不得转载: ES 的 Restful风格: Restful是一种面向资源的架构风格,可以简单理解为:使用URL定位资源,用HTTP动词(GET,POST,DELETE,PUT) ...
- 【收集】embed
序 链接 备注 1 适用于嵌入式单片机的差分升级通用库+详细教程_风吹花中花吹风的博客-CSDN博客 差分升级包制作与还原 2 前言 · 给新手的两轮自平衡小车开发实战指南 (miaowlabs.co ...
- 神经网络优化篇:详解局部最优的问题(The problem of local optima)
局部最优的问题 在深度学习研究早期,人们总是担心优化算法会困在极差的局部最优,不过随着深度学习理论不断发展,对局部最优的理解也发生了改变.向展示一下现在怎么看待局部最优以及深度学习中的优化问题. 这是 ...
- sql server 数据恢复
1) 备份当前数据库的事务日志:BACKUP LOG [数据库名] TO disk= N'备份文件名' WITH NORECOVERY 2) 恢复一个误删除之前的完全备份:RESTORE DATABA ...
- [转帖]金仓数据库KingbaseES分区表 -- 声明式创建分区表
https://www.modb.pro/db/638045 1. 创建分区表同时创建分区 1.1 准备环境 # 创建分区表同时创建分区 create table tb1(id bigint,stat ...
- [转帖]Jmeter 压测中配置https证书
本文章 主要介绍证书的获取.处理.配置到jmeter中. 1. 获取证书 首先:谷歌浏览器 打开网站,点击 地址栏的锁(表示https),选择 "证书"---"隐私.搜索 ...