解决线程不安全的方式(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 ...
随机推荐
- AcWing 每日一题 - 暑假
本篇解题记录题源来自 AcWing 的每日一题 · 暑假 补题链接:Here Week 1 星期四 AcWing 3761. 唯一最小数 利用 map 存出现过数的下标和次数即可 vector< ...
- 数论(7):康托展开&逆康托展开
康托展开可以用来求一个 \(1\sim n\) 的任意排列的排名. 什么是排列的排名? 把 \(1\sim n\) 的所有排列按字典序排序,这个排列的位次就是它的排名. 时间复杂度? 康托展开可以在 ...
- 领域驱动设计(DDD)实践之路(三):如何设计聚合
本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/oAD25H0UKH4zujxFDRXu9Q作者:wenbo zhang [领域驱动设计实践之路 ...
- 五、mycat水平分库
系列导航 一.Mycat实战---为什么要用mycat 二.Mycat安装 三.mycat实验数据 四.mycat垂直分库 五.mycat水平分库 六.mycat全局自增 七.mycat-ER分片 一 ...
- 三、mycat实验数据
系列导航 一.Mycat实战---为什么要用mycat 二.Mycat安装 三.mycat实验数据 四.mycat垂直分库 五.mycat水平分库 六.mycat全局自增 七.mycat-ER分片 最 ...
- LightOJ 1094
题意:就是求一个树的直径,也就是求任意两点的最大距离. 做法:跑两遍DFS,详见代码. #include<iostream> #include<cstdio> #include ...
- 定期发送邮件功能-outlook与腾讯邮箱
一.背景:定期发送邮件功能挺好用的,可以帮忙我们在特殊的时间点发送邮件,以及实现无人推送的功能 二.outlook的实现1.首先编辑好邮件保存至草稿 2.选项-延迟传递,设置不早于传递的时间,点击发送 ...
- connect() failed (113: No route to host) while connecting to upstream
转载请注明出处: 用docker 搭建的服务,今天重启了一个容器之后,请求这个服务的接口都变成了 502, 但通过docker 查看日志,发现没有异常,端口也都是正常,在nginx的日志中看到了这段错 ...
- jenkins构建报错: Send build artifacts over SSH' changed build result to UNSTABLE
原因包括: ssh配置的用户没有相关的权限. 最好是配置root用户
- vscode插件 - 浏览器中自动刷新 Live Server