线程安全
发布日期:2021-06-27 12:56:02 浏览次数:27 分类:技术文章

本文共 4659 字,大约阅读时间需要 15 分钟。

多线程之间由于抢占式运行,存在线程不安全的问题。如:

public class Demo_safe {
public static void main(String[] args) {
//线程不安全 Runnable run = new Ticket(); new Thread(run).start(); new Thread(run).start(); new Thread(run).start(); } static class Ticket implements Runnable{
//票数 private int count = 10; @Override public void run() {
while (count>0){
//卖票 System.out.println("准备卖票"); try {
Thread.sleep(1000); } catch (InterruptedException e) {
e.printStackTrace(); } count--; System.out.println("出票成功,余票:"+count); } } }}
输出:准备卖票准备卖票准备卖票出票成功,余票:8准备卖票出票成功,余票:9准备卖票出票成功,余票:7准备卖票出票成功,余票:4准备卖票出票成功,余票:5准备卖票出票成功,余票:6准备卖票出票成功,余票:1准备卖票出票成功,余票:2准备卖票出票成功,余票:3准备卖票出票成功,余票:-2出票成功,余票:-1出票成功,余票:0

出现了负数,明显不合理,存在不安全问题

实现线程安全有如下方法:

一、同步代码块

格式: synchronized(锁对象){}

注意: 一定要所有线程都看同一把锁才能保证排队,以保证线程安全。

import java.io.ObjectOutputStream;public class Demo_safe1 {
public static void main(String[] args) {
//线程不安全 Runnable run = new Ticket(); new Thread(run).start(); new Thread(run).start(); new Thread(run).start(); } static class Ticket implements Runnable {
//票数 private int count = 10; private Object o = new Object(); @Override public void run() {
while (true) {
synchronized (o) {
if (count > 0) {
//卖票 System.out.println("准备卖票"); try {
Thread.sleep(1000); } catch (InterruptedException e) {
e.printStackTrace(); } count--; System.out.println(Thread.currentThread().getName() + "出票成功,余票:" + count); }else {
break; } } } } }}
准备卖票Thread-0出票成功,余票:9准备卖票Thread-0出票成功,余票:8准备卖票Thread-0出票成功,余票:7准备卖票Thread-0出票成功,余票:6准备卖票Thread-0出票成功,余票:5准备卖票Thread-0出票成功,余票:4准备卖票Thread-2出票成功,余票:3准备卖票Thread-2出票成功,余票:2准备卖票Thread-2出票成功,余票:1准备卖票Thread-2出票成功,余票:0

二、同步方法

public class Demo_safe2 {
public static void main(String[] args) {
//线程不安全 Runnable run = new Ticket(); new Thread(run).start(); new Thread(run).start(); new Thread(run).start(); } static class Ticket implements Runnable {
//票数 private int count = 10; @Override public void run() {
while (true) {
boolean flag = sale(); if (!flag){
break; } } } public synchronized boolean sale(){
if (count > 0) {
//卖票 System.out.println("准备卖票"); try {
Thread.sleep(1000); } catch (InterruptedException e) {
e.printStackTrace(); } count--; System.out.println(Thread.currentThread().getName()+"出票成功,余票:" + count); return true; }else {
return false; } } }}

以上同步代码块 与 同步方法 都属于隐式锁

三、显示锁Lock

其子类 ReentrantLock

import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class Demo_safe3 {
public static void main(String[] args) {
//线程不安全 Runnable run = new Ticket(); new Thread(run).start(); new Thread(run).start(); new Thread(run).start(); } static class Ticket implements Runnable {
//票数 private int count = 10; //显示锁 //private Lock l = new ReentrantLock(true); 当传入参数"true",则表示为公平锁 private Lock l = new ReentrantLock(); @Override public void run() {
while (true) {
l.lock(); if (count > 0) {
//卖票 System.out.println("准备卖票"); try {
Thread.sleep(1000); } catch (InterruptedException e) {
e.printStackTrace(); } count--; System.out.println(Thread.currentThread().getName()+"出票成功,余票:" + count); }else {
break; } l.unlock(); } } }}

转载地址:https://blog.csdn.net/weixin_43454088/article/details/117338555 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Runnable与Callable
下一篇:多线程的实现

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年03月18日 11时39分12秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

linux搭建java开发环境_Linux搭建Java开发环境 2019-04-21
mysql null 0 空_MySQL中 null与not null和null与空值''的区别 2019-04-21
java 内存管理 知乎_[知乎]Java 语言的 GC 为什么不实时释放内存? 2019-04-21
java optional_JAVA Optional总结 2019-04-21
java格式化时间博客园_Java 日期格式化工具类 2019-04-21
java课设电子门禁_中控门禁pullSdk Java demo 中控智慧门禁系统 - 下载 - 搜珍网 2019-04-21
java用cmd编译access数据库_java直接存取MS Access的mdb数据库文件 2019-04-21
java创建一个图形类getv_java建立类和对象分糖果 2019-04-21
java 新增注解_java annotation(如何创建新的注解)小结 2019-04-21
mysql 函数定义常量_php如何定义一个自定义常量 2019-04-21
约瑟夫问题java 递归_从约瑟夫问题的递归实现的问题说起 2019-04-21
mysql 索引表的应用_MySQL查询优化之索引的应用详解 2019-04-21
用java实现动态排序_关于Java动态分组排序的问题(Android中需要将数据排序给RecyclerView使用)... 2019-04-21
Java中文jsp页面_java中文乱码解决之道(七)—–JSP页面编码过程 2019-04-21
java只读xml文件头_为了生成只读的接口和xml,并命名结尾为MapperR.java和MapperR.xml... 2019-04-21
neatdm路径_网易有爱插件设置教程-网易有爱插件游戏路径如何设置 2019-04-21
oracle迁移mysql验证_ORACLE 迁移MYSQL 随笔 2019-04-21
类型不匹配 java_java – 与泛型类型不匹配 2019-04-21
专科转行学java_大专女生想转行做IT,应该先学哪一块? 2019-04-21
php取汉字拼音首字母,php获取汉字拼音首字母的函数(真正可以使用的) 2019-04-21