如何解决多线程并发访问一个资源的安全性问题?

原子操作所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切[1] 换到另一个线程)。
关于我对原子操作的理解:原子操作就类似于化学中的原子为不可分割的单位,也就是如果把需要操作的代码块能够顺序执行中间不为被干扰。
这样就不会出现线程不安全情况(案例中的购票系统出现负数的情况),这种原子操作思想还是挺有用的,在这提提自己也不了解=-=。
解决方案:保证打印编号和操作必须同步执行:System.out.println(Thread.currentThread().getName()+”—卖出的票”+tickets–);
也就是上述代码中ticket–与输出同步执行,不能因为某个线程输出后就休眠而不执行减减操作。


方式一、同步代码块:
语法:

        synchronize(同步锁){需要同步操作的代码}

案例:

package com.test;//线程安全  
public class Main {  public static void main(String[] args){  SaleThread saleThread=new SaleThread();  new Thread(saleThread,"线程一").start();  new Thread(saleThread,"线程二").start();  new Thread(saleThread,"线程三").start();  new Thread(saleThread,"线程四").start();  }  
}  
class SaleThread implements Runnable{  private int tickets=10;  public void run(){  //synchronized (this) {while(tickets>0){  try{  Thread.sleep(10);  }catch(InterruptedException e){  e.printStackTrace();  }  System.out.println(Thread.currentThread().getName()+"---卖出的票"+tickets--);  // } } }  
}  

*输出结果:
线程二—卖出的票10
线程一—卖出的票9
线程四—卖出的票8
线程三—卖出的票7
线程二—卖出的票5
线程一—卖出的票6
线程三—卖出的票4
线程四—卖出的票3
线程一—卖出的票1
线程二—卖出的票2
线程三—卖出的票-1
线程四—卖出的票0*
分析:上述结果中出现负数和0情况(如果数据量大还会出现重复情况)。


方式二、同步方法
使用synchronized修饰的方法就叫同步方法,表示a线程在执行该方法的时候其他线程只能等待。
代码:

        synchronized public void run(){  while(tickets>0){  try{  Thread.sleep(10);  }catch(InterruptedException e){  e.printStackTrace();  }  System.out.println(Thread.currentThread().getName()+"---卖出的票"+tickets--);  }
    **问题来了上述代码中synchronized中的同步锁是谁?**对于非static方法同步锁就是this对于static方法,我们使用当前方法所在类的字节码对象(当前类名.class)

方式三、同步锁-锁机制lock
为了保证每个线程都能正常执行原子操作,java引入了线程同步机制。
同步监听对象/同步锁/同步监听器/互斥锁(a进去b被排斥,保证只有一个进程执行)
对象的同步锁只是一个概念,可以想象为在对象上标记一个锁。
java程序运行使用任何对象作为同步监听对象,但是一般的,我们试验当前并发访问的共同资源作为同步监听对象。
注意:在任何时候,最多允许一个线程拥有同步锁,谁拿到锁就进入代码块,其他线程只能等待。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/509736.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实例浅析epoll的水平触发和边缘触发,以及边缘触发为什么要使用非阻塞IO

一.基本概念 我们通俗一点讲: Level_triggered(水平触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据一次性全部读写完(如…

Kafka开发指南之 如何Kafka 事务型生产者,保证生产者exactly once

目录 至少一次(at least once) 最多一次(at most once) 精确一次(exactly once) 幂等性 幂等性作用范围 实现方法 代码 事务 事务作用范围 实现方法 代码 我们知道Kafka的消息交付可靠性保障分为…

UML序列图

UML学习(三)-----序列图 UML的模型中可分为两种,动态模型和静态模型。用例图、类图和对象图都是UML中的静态结构模型。而在UML系统动态模型的其中一种就是交互视图,它描述了执行系统功能的各个角色之间相互传递消息的顺序关系。序…

OpenTSDB 开发指南之 查询数据

前面博主写了一篇文章去介绍opentsdb的http接口的使用方法,但是某一些接口的使用还是比较复杂,这篇文章会通过example来详细讲述opentsdb的一些特性。 本文的举的例子有这些: 基本的写入和查询数据的注释和说明子查询查询中的filters使用查询数据的rat…

OpenTSDB 开发指南之 Api操作数据

/api/put 请求方式:post请求参数: 参数说明examplesummary返回主要摘要/api/put?summarydetails返回详细信息/api/put?detailssync是否同步,即是否等待数据都写入成功后才返回结果/api/put?syncsync_timeout返回结果之前的等待时间/api/p…

xshell下利用SFTP传输文件

SFTP是基于SSH的文件传输协议,与ZMODEM相比具有更加安全且更为快速的文件传输功能。 如何利用SFTP接收文件: 在本地提示以sftp命令登陆拟要接收文件的主机。 Xshell:> sftp hostname在sftp提示下以get命令接收需要的文件。 sftp:/home/user21>get filenam…

libcurl使用方法

原文地址:http://curl.haxx.se/libcurl/c/libcurl-tutorial.html 译者:JGood(http://blog.csdn.net/JGood ) 译者注:这是一篇介绍如何使用libcurl的入门教程。文档不是逐字逐句按原文翻译,而是根据笔者对libcurl的理解&#xff0c…

OpenTSDB 开发指南之 Grafana 展示OpenTSDB监控数据

目录 准备数据 在Grafana创建OpenTSDB连接 创建一个仪表盘 统计 准备数据 将数据插入OpenTSDB {"metric":"jast.data","value":1023,"timestamp":1588742563,"tags":{"type":"jast-graph-data"}}…

linux重启后地址不是之前设置的静态地址的解决方案

按照以下步骤进行安装 1. vi /etc/hosts 修给域名匹配 2. vi /etc/sysconfig/network 修改主机名称 3. vi /etc/sysconfig/network-scripts/ifcfg-eth0 修改主机IP 4. vi /etc/udev/rules.d/70-persistent-net.rules 把里面的eth0删掉,把eth1名称改为eth0

CDH 版本 Kafka 外网设置

登陆CDH页面,进入Kafka配置页面 搜索 advertised 修改advertised.host.name,这里我们有三台Broker,我们把每台的外网ip填写到对应的机器上 advertised.port不填写 我们kafka的端口设置的是9099 将外网端口9099开放,允许外网访问 (这里不做介绍

SQLite、MySQL和PostgreSQL 三种关系数据库比较

关系型数据库的使用已经有相当长的时间了。它们变得流行起来托了管理系统的福,关系模型被实现得相当的好,并且被证明是操作数据的好方法(特别是事务性强的应用)。 在这篇DigitalOcean文章中,我们将尝试理解一些最常用、…

Ecilpse常用快捷键

Alt ? #代码提示ctrl l #去某一行ctrl D #删掉光标所在的一行ctrl shift r #访问某个文件ctrl shiif f #格式化ctrl shift o #包的引入alt 方向键向下 #光标所在行向下移alt 方向键向上 # 光标所在行向上移ctrl alt 方向键向下 #光标所在行向…

OpenTSDB 安装

下载目录 https://github.com/OpenTSDB/opentsdb/releases https://github.com/OpenTSDB/opentsdb/releases/download/v2.4.0/opentsdb-2.4.0.noarch.rpm 安装 GnuPlot yum install gnuplot -y 直接安装OpenTSDB会报错 [rootecs-t-001-0001 openTSDB]# rpm -ivh opentsdb-2.…

leveldb使用指南

这篇文章是levelDB官方文档的译文,原文地址:LevelDB library documentation 这篇文章主要讲leveldb接口使用和注意事项。 leveldb是一个持久型的key-value数据库。key,value可以是任意的字节数组,key之间是有序的。key的比较函数可以由用户指定。 1. 打…

java中同步锁的原理和实现

接口 Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition 对象。 锁是控制多个线程对共享资源进行访问的工具。通常,锁提供了对共享资…

HugeGraph 配置参数

gremlin-server.yaml 参数名称参数说明默认值scriptEvaluationTimeout查询超时时间,单位毫秒30000rest-server.properties 参数名称参数说明默认值restserver.max_worker_threads服务器最大工作线程2*cpurestserver.min_free_memory当服务器内存小于该值时&#x…

本地yum仓库以及网络版yum的私有仓库详细的安装配置

本地仓的配置 第一步:开启CD/DVD 设备,并且把centos镜像链接添加至设备中 第二步:创建一个 文件夹用来挂在 光驱文件 mkdir /mnt/cdrom (通常约定挂载在/mnt目录下 ) 第三步:mount -t iso9660 -o ro /de…

LevelDB简述

转自:http://www.cnblogs.com/melons/p/5791855.html 既然开始了,哪有停下的道理,先了解一下Levedb的关荣历史、完美现在和光辉的未来: Leveldb: 1.Leveldb是一个google实现的非常高效的kv数据库,目前能够支持billion级…

HBase原理 – snapshot 快照

目录 snapshot(快照)基础原理 snapshot能实现什么功能? hbase snapshot用法大全 hbase snapshot分布式架构-两阶段提交 snapshot核心实现 clone_snapshot如何实现呢? 其他需要注意的 参考文献 更多信息可参考《…

linux如何自动化部署脚本实现免密登录并访问资源

任务把weijie主机jdk文件安装到weijie1中。 首先再各台主机中安装必要的命令: expect、wget、httpd、ssh 执行命令 如:expect提示命令不存在,则分别安装命令 yum install expect yum install wget yum install httpd yum install ssh 开…