一、同步代码块

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)的更多相关文章

  1. java 22 - 13 多线程之解决线程安全问题的实现方式2

    上一章说了,解决线程安全问题的实现方式1是使用同步代码块 同时也知道了,同步代码块的锁对象是任意对象:(Object obj ;  Demo d;)这些都行 那么,现在来说解决线程安全问题的实现方式2 ...

  2. java 22 - 12 多线程之解决线程安全问题的实现方式1

    从上一章知道了多线程存在着线程安全问题,那么,如何解决线程安全问题呢? 导致出现问题的原因: A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 上一章的程序,上面那3条都具备, ...

  3. Java并发编程:Java创建线程的三种方式

    目录 引言 创建线程的三种方式 一.继承Thread类 二.实现Runnable接口 三.使用Callable和Future创建线程 三种方式的对比 引言 在日常开发工作中,多线程开发可以说是必备技能 ...

  4. Java之解决线程安全问题的方式三:Lock锁

    import java.util.concurrent.locks.ReentrantLock; /** * 解决线程安全问题的方式三:Lock锁 --- JDK5.0新增 * * 1. 面试题:sy ...

  5. java线程安全问题以及使用synchronized解决线程安全问题的几种方式

    一.线程安全问题 1.产生原因 我们使用java多线程的时候,最让我们头疼的莫过于多线程引起的线程安全问题,那么线程安全问题到底是如何产生的呢?究其本质,是因为多条线程操作同一数据的过程中,破坏了数据 ...

  6. java——多线程的实现方式、三种办法解决线程赛跑、多线程数据同步(synchronized)、死锁

    多线程的实现方式:demo1.demo2 demo1:继承Thread类,重写run()方法 package thread_test; public class ThreadDemo1 extends ...

  7. Lock锁方式解决线程安全问题

    在JDK5.0之后新增加了一种更强大的线程同步机制---通过显示定义同步锁来实现线程同步解决线程安全问题.同步锁使用Lock对象充当. java.util.concurrent.locks.lock接 ...

  8. java并发之如何解决线程安全问题

    并发(concurrency)一个并不陌生的词,简单来说,就是cpu在同一时刻执行多个任务. 而Java并发则由多线程实现的. 在jvm的世界里,线程就像不相干的平行空间,串行在虚拟机中.(当然这是比 ...

  9. Java实现线程的三种方式和区别

    Java实现线程的三种方式和区别 Java实现线程的三种方式: 继承Thread 实现Runnable接口 实现Callable接口 区别: 第一种方式继承Thread就不能继承其他类了,后面两种可以 ...

  10. Java基础_通过模拟售票情景解决线程不安全问题

    用代码来模拟铁路售票系统,实现通过四个售票点发售某日某次列车的100张车票,一个售票点用一个线程表示 第一种方法:通过继承Thread类的方法创建线程 package com.Gary1; publi ...

随机推荐

  1. springboot线程池的使用方式1

    线程池的创建方法 总共有 7 种,但总体来说可分为 2 类: 一类是通过 ThreadPoolExecutor 创建的线程池: 另一个类是通过 Executors 创建的线程池. 1. Executo ...

  2. 清洁低碳环保新能源,3D 光伏与光热发电站可视化

    前言 碳达峰.碳中和成为今年两会"热词",在国家政府工作报告中指出,扎实做好碳达峰.碳中和各项工作,制定 2030 年前碳排放达峰行动方案,优化产业结构和能源结构,实现低碳环保节能 ...

  3. freeswitch的ACL规则

    概述 freeswitch是一款好用的VOIP开源软交换平台. VOIP公共网络中的安全问题是最重要的问题,我们必须对网络端口的访问权限做出限制. ACL全称Access Control List,意 ...

  4. mysql 主从状态查询及恢复

    转载请注明出处: 备机执行主备恢复的命令: 今天早上打开电脑,验证测试环境的服务时,发现服务挂了,当登录服务器查看日志的时候,发现数据库连不上了,紧忙登上数据库服务器,发现数据库mysql 的服务挂了 ...

  5. feign接口自动生成工具

    最近发现开发spring cloud时,编写feign接口是一件痛苦的事,不仅要编写feign接口,还有fallback.请求参数和返回值等,大量重复工作,很浪费时间. 于是便想到可以编写工具自动生成 ...

  6. pojo层、dao层、service层、controller层的作用

    分层解耦介绍 1.pojo层(model) 实体层 数据库在项目中的类 model是模型的意思,与entity.domain.pojo类似,是存放实体的类. 类中定义了多个类属性,并与数据库表的字段保 ...

  7. 问题--去除CSDN水印

    1.问题如上 有时候需要使用其中的图片,但是水印很让人烦恼 确实可以用PS中的修复画笔工具,修复工具等进行处理 但是当水印覆盖到字体时,就会破坏到原有字体 2.解决方式 从CSDN添加水印的方式入手 ...

  8. NodeJS安装指南(Mac)

    nvm,node,npm之间的区别 nvm:nodejs 版本管理工具. 也就是说:一个 nvm 可以管理很多 node 版本和 npm 版本. nodejs:在项目开发时的所需要的代码库 npm:n ...

  9. k8s~istio的安装与核心组件

    安装istio 在线安装:https://istio.io/latest/docs/setup/getting-started/#download 或者直接在这里下载:https://github.c ...

  10. [转帖]【教程】如何在不同架构打包Docker镜像

    https://docs.qsnctf.com/qsnctf/37674.html 前言 大家在使用Docker的时候经常会遇到一个问题,就是受用机和本级不是同一架构.就比如小编使用的就是新版本的Ma ...