- 浏览: 189180 次
- 性别:
- 来自: 杭州
博客专栏
-
Java技术分享
浏览量:0
文章分类
最新评论
-
masuweng:
学习了,学习了
mybatis是如何防止SQL注入的 -
somefuture:
终于知道了#$的区别
mybatis是如何防止SQL注入的 -
masuweng:
...
tomct处理请求的流程 -
zhp8341:
masuweng 写道寻求cas的更多例子, http://w ...
JUC之CAS -
臻是二哥:
java.util.concurrent包中到处都使用了CAS ...
JUC之CAS
不知道各位童鞋是否干过在程序主进程中嵌入IO操作这样“任性”的事情,笔者曾经干过,而且那时候还觉得自己很棒。没办法,那时候还年轻啊。后来随着学习的深入,知道了有nio这种神一样的东西。但如果有其他方案,至少笔者是不会使用nio这个类的。毕竟程序的易读性还是很重要滴。多数时候,我们完全可以使用多线程和IO阻塞来代替非阻塞IO。
最近读了下经典《Java并发编程实践》,大师的书的确很棒,好了不说废话了,来写下我的笔记吧。
并发编程主要需要解决安全性,活跃性和性能的问题。下面是个人的理解:
1 安全性:程序可以确定的按照我们希望的时序执行。
2 活跃性:程序最终会输出正确的结果
3 性能:程序多长时间能输出正确的结果。
对于程序设计人员,我们需要在上面的3点之间寻找一种平衡,一种在满足安全性基础之上的平衡。
首先,我觉得有一个问题需要解决,那就是什么时候使用并发编程:并发编程一定是在需要的时候使用,什么是需要的时候?比如有一天,你的leader和你说,系统太慢了,以至于用户都快跑光了(哈哈,有点夸张),这个时候你就需要考虑一下是否可以使用多线程来做点什么。如果你确实发现了代码中有太多可以用多线程提升的地方,那么,。just do it。否则,还是不要轻易改变了,毕竟“稳定压倒一切吗”。先保证稳定在考虑性能。
当决定使用多线程的时候,我们就需要考虑安全性,活跃性以及性能了。
所谓的安全性,就是要求我们能够编写线程安全的代码,他的核心在于处理那些可以被多个线程共享的可变的变量。就像我在黑体部分说的,需要考虑线程安全的情况,一定是有下列3个条件:
1 一个可以被多个线程访问的变量
2 这个变量是共享的
3 这个变量的值是可以改变的
但你的程序中出现了这3个情况的时候,那么要小心了,需要考虑线程安全问题了。说白了,就是对于这个共享变量的访问时候的同步问题。就是常见的“读-改-写”和“核对后执行”情况。
比如我写了一个类:
在这个例子中,MyThread类的变量count是可以被多个线程访问的,是共享的,是可变的(瞧,满足3个条件),我们需要考虑线程安全问题了。这是一个典型的“读-改-写”的问题,理论上我当然希望每个线程都能一口气执行完count++这条语句,但事实常常不是这样,可能thread-1刚刚读取到count为0,CPU就调度给了thread-2,这个时候thread-2读取到的count也是0,很显然,程序没有按照我们希望的时序执行,我们说他是不安全的。
我们可以使用线面的方式来让他变成线程安全的.
但是有些时候,并不总是有这样的第三方的类可以给我们使用的。
可能我们写了一个类,来根据一个请求的1-9的阿拉伯数字返回对应的大写汉字
尽管service方法被多个线程执行,但不存在安全性的问题(没有多个线程共享的变量);这个时候,如果为了提高性能,需要将上一次请求的数据存储起来,我们来看:
在上面的代码中,出现了多个线程可以访问可变的的共享变量num和str,这时候需要考虑线程安全的问题了。有个最简单的方案将他变为线程安全的:
程序设计人员不去具体分析哪些代码是需要同步的,而是同步一个大的区域,讲所有共享变量圈在里面,当然这样做实现了线程安全。但是没有考虑性能的问题。假设getHanziByNum()是一个非常耗时间的操作,那么同步方法service的执行时间将会非常慢,而整个方法有事同步的,很可能我们的并发代码 运行的性能比串行的还要差(创建和销毁线程需要时间,尽管很短)。因此,我们需要一些更加细粒度的同步,而不是像上面的粗粒度的同步。
上面的类是线程安全的,显然他比之前一个在性能上会更有优势。所以在解决多线程安全性的问题上,关于同步的粒度的大小需要我们仔细的研究,力度大一点可能实现起来简单,但是性能不一定太好。粒度太小的话,可能实现起来难度大,容易出错,怎么做到合适,需要我们自己权衡。
这个时候,如果我还想保存命中的变量
可以看到,所有共享变量出现的地方都被加了锁(即同步操作),只不过同步的力度不同罢了。
综上所述,关于并发,我们的思路大概是这样的:
1 是否使用并发
2 如果使用用并发,哪些共享变量需要考虑安全性
3 对于需要考虑安全性的那些共享变量,要记得为每一个加锁
4 加锁的粒度粗细的权衡
最近读了下经典《Java并发编程实践》,大师的书的确很棒,好了不说废话了,来写下我的笔记吧。
并发编程主要需要解决安全性,活跃性和性能的问题。下面是个人的理解:
1 安全性:程序可以确定的按照我们希望的时序执行。
2 活跃性:程序最终会输出正确的结果
3 性能:程序多长时间能输出正确的结果。
对于程序设计人员,我们需要在上面的3点之间寻找一种平衡,一种在满足安全性基础之上的平衡。
首先,我觉得有一个问题需要解决,那就是什么时候使用并发编程:并发编程一定是在需要的时候使用,什么是需要的时候?比如有一天,你的leader和你说,系统太慢了,以至于用户都快跑光了(哈哈,有点夸张),这个时候你就需要考虑一下是否可以使用多线程来做点什么。如果你确实发现了代码中有太多可以用多线程提升的地方,那么,。just do it。否则,还是不要轻易改变了,毕竟“稳定压倒一切吗”。先保证稳定在考虑性能。
当决定使用多线程的时候,我们就需要考虑安全性,活跃性以及性能了。
所谓的安全性,就是要求我们能够编写线程安全的代码,他的核心在于处理那些可以被多个线程共享的可变的变量。就像我在黑体部分说的,需要考虑线程安全的情况,一定是有下列3个条件:
1 一个可以被多个线程访问的变量
2 这个变量是共享的
3 这个变量的值是可以改变的
但你的程序中出现了这3个情况的时候,那么要小心了,需要考虑线程安全问题了。说白了,就是对于这个共享变量的访问时候的同步问题。就是常见的“读-改-写”和“核对后执行”情况。
比如我写了一个类:
@UnThreadSafe class MyThread extends Thread { private int count=0; public void run(){ count++; System.out.println("counter="+count); } }
在这个例子中,MyThread类的变量count是可以被多个线程访问的,是共享的,是可变的(瞧,满足3个条件),我们需要考虑线程安全问题了。这是一个典型的“读-改-写”的问题,理论上我当然希望每个线程都能一口气执行完count++这条语句,但事实常常不是这样,可能thread-1刚刚读取到count为0,CPU就调度给了thread-2,这个时候thread-2读取到的count也是0,很显然,程序没有按照我们希望的时序执行,我们说他是不安全的。
我们可以使用线面的方式来让他变成线程安全的.
@ThreadSafe class MyThread extends Thread { private final AtomicLong count=new AtomicLong(0); public void run(){ int tmp=count.incrementAndGet(); System.out.println("counter="+tmp); } }
但是有些时候,并不总是有这样的第三方的类可以给我们使用的。
可能我们写了一个类,来根据一个请求的1-9的阿拉伯数字返回对应的大写汉字
public class MyServlet implements Servlet { public void service(ServletRequest req,ServletResponse res){ int i=getNum(req); String str=getHanziByNum(i); responseHanzi(res,i); } }
尽管service方法被多个线程执行,但不存在安全性的问题(没有多个线程共享的变量);这个时候,如果为了提高性能,需要将上一次请求的数据存储起来,我们来看:
@UnThreadSafe public class MyServlet implements Servlet { private int num; private String str; public void service(ServletRequest req,ServletResponse res){ int i=getNum(req); if(i==num) responseHanzi(res,str); else String str1=getHanziByNum(i); num=i; str=str1; responseHanzi(res,str1); } }
在上面的代码中,出现了多个线程可以访问可变的的共享变量num和str,这时候需要考虑线程安全的问题了。有个最简单的方案将他变为线程安全的:
@ThreadSafe public class MyServlet implements Servlet { private int num; private String str; public synchronized void service(ServletRequest req,ServletResponse res){ int i=getNum(req); if(i==num) responseHanzi(res,str); else String str1=getHanziByNum(i); num=i; str=str1; responseHanzi(res,str1); } }
程序设计人员不去具体分析哪些代码是需要同步的,而是同步一个大的区域,讲所有共享变量圈在里面,当然这样做实现了线程安全。但是没有考虑性能的问题。假设getHanziByNum()是一个非常耗时间的操作,那么同步方法service的执行时间将会非常慢,而整个方法有事同步的,很可能我们的并发代码 运行的性能比串行的还要差(创建和销毁线程需要时间,尽管很短)。因此,我们需要一些更加细粒度的同步,而不是像上面的粗粒度的同步。
@ThreadSafe public class MyServlet implements Servlet { private int num; private String str; public void service(ServletRequest req,ServletResponse res){ int i=getNum(req); String str1=null; synchronized(this){ if(i==num) str1=str; } if(str1=null){ str1=getHanziByNum(i); synchronized(this){ num=i; str=str1; } } responseHanzi(res,str1); } }
上面的类是线程安全的,显然他比之前一个在性能上会更有优势。所以在解决多线程安全性的问题上,关于同步的粒度的大小需要我们仔细的研究,力度大一点可能实现起来简单,但是性能不一定太好。粒度太小的话,可能实现起来难度大,容易出错,怎么做到合适,需要我们自己权衡。
这个时候,如果我还想保存命中的变量
@ThreadSafe public class MyServlet implements Servlet { private int num; private String str; private int hits; private int totalHits; public synchronized double getHitRadio{ return hits/totalHits; } public void service(ServletRequest req,ServletResponse res){ int i=getNum(req); String str1=null; synchronized(this){ totalHits++; if(i==num){ str1=str; hits++; } } if(str1=null){ str1=getHanziByNum(i); synchronized(this){ num=i; str=str1; } } responseHanzi(res,str1); } }
可以看到,所有共享变量出现的地方都被加了锁(即同步操作),只不过同步的力度不同罢了。
综上所述,关于并发,我们的思路大概是这样的:
1 是否使用并发
2 如果使用用并发,哪些共享变量需要考虑安全性
3 对于需要考虑安全性的那些共享变量,要记得为每一个加锁
4 加锁的粒度粗细的权衡
发表评论
-
精心准备的讲解Java多线程的知乎Live
2018-09-02 21:39 704花了一个月的时间,结合自己的理解,制作了一个以图片的方式讲解J ... -
在知乎推出Java求职类专栏文章
2018-08-27 12:06 790从昨天起,笔者开始在知乎推出Java求职类专栏文章,主要涉及一 ... -
JUC之AQS
2016-07-27 15:49 1273AQS是同步框架,它进行 ... -
JUC之CAS
2016-07-27 10:56 1664JUC是java.util.concurrent包 ... -
JAVA并发-线程状态和线程组
2016-07-18 14:14 1328在Java中,线程有6种基本状态,理解这6种基本状态之间的关系 ... -
JAVA并发-条件队列
2016-07-02 09:57 1115在JVM系列博客http://yizhen ... -
JAVA并发-中断处理和任务取消
2016-06-27 22:42 1304中断处理 在java程序中 ... -
JAVA并发-显式锁(二)
2016-06-06 09:25 1024在上一篇博客《JAVA并发-显式锁(一)》中介绍了Lock和R ... -
JAVA并发-显式锁(一)
2016-06-05 20:40 891JAVA语言除了提供内置锁synchronized,还在JDK ... -
JAVA并发-减少锁的竞争
2016-06-04 16:01 1911降低锁的竞争可以提高 ... -
JAVA并发-3种典型的死锁
2016-06-03 19:54 1621在JAVA并发编程中,我们 ... -
JAVA并发-3种典型的死锁
2016-06-03 10:02 10在JAVA并发编程中,我们 ... -
JAVA并发-ThreadPoolExecutor线程池的使用
2016-05-30 16:19 2356在博客JAVA并发-Executor任务执行框架中曾说过,Ex ... -
JAVA并发-Executor任务执行框架
2016-05-27 19:10 432首先介绍两个重要的接 ... -
JAVA并发-DCL与JMM
2016-04-26 19:21 1619首先必须声明,在volatil ... -
JAVA并发- 典型连接池的实现
2016-04-22 10:44 1239package com.xyz.connpool; pu ... -
JAVA并发-构建可靠的结果缓存
2016-04-10 16:58 55在学习了前面关于多线程的博客之后,下面来介绍一个构建可靠结果缓 ... -
JAVA并发-并发编程常用类
2016-04-08 11:07 991在讲同步工具类之前,笔者想先介绍一下Runnable,Call ... -
JAVA并发-同步容器和并发容器
2016-04-07 19:02 698常见的同步容器类包括V ... -
JAVA并发-开发线程安全类
2016-04-01 10:23 840我们知道,面向对象的 ...
相关推荐
Java-美妆神域_3rm1m18i_221-wx.zip
51单片机的温度监测与控制(温控风扇)
电赛案例,C++简单的智能家居系统,其中包含了温度监测、光照控制和报警系统。该系统可以: 监控室内温度:当温度超过设定阈值时,触发警报。 自动调节光照:根据光线传感器的值自动调节LED灯的亮度。 入侵检测:通过红外传感器检测入侵,并触发警报。
圣诞树 html版 可修改祝福语。 记事本或vscode编辑html文件:ctrl+F寻找”myLabels“关键词,定位到该处即可修改祝福语
【资源说明】 基于python编写的selenium自动化测试框架,采用PO模式,页面元素采用yaml进行管理资料齐全+详细文档+高分项目+源码.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
屏幕截图 2024-12-21 170434
基于SpringBoot的学生信息管理系统(前后端源码+数据库+文档+运行截图) 学生信息管理 班级信息管理 教师信息管理 课程信息管理 选课信息管理 考勤信息管理 请假信息管理 成绩信息管理 基于SpringBoot的学生信息管理系统(前后端源码+数据库+文档+运行截图) 学生信息管理 班级信息管理 教师信息管理 课程信息管理 选课信息管理 考勤信息管理 请假信息管理 成绩信息管理基于SpringBoot的学生信息管理系统(前后端源码+数据库+文档+运行截图) 学生信息管理 班级信息管理 教师信息管理 课程信息管理 选课信息管理 考勤信息管理 请假信息管理 成绩信息管理基于SpringBoot的学生信息管理系统(前后端源码+数据库+文档+运行截图) 学生信息管理 班级信息管理 教师信息管理 课程信息管理 选课信息管理 考勤信息管理 请假信息管理 成绩信息管理基于SpringBoot的学生信息管理系统(前后端源码+数据库+文档+运行截图) 学生信息管理 班级信息管理 教师信息管理 课程信息管理 选课信息管理 考勤信息管理
径向基函数内核 – 机器学习 内核在将数据转换为更高维空间方面发挥着重要作用,使算法能够学习复杂的模式和关系。在众多的内核函数中,径向基函数(RBF)内核作为一种多功能且强大的工具脱颖而出。在本文中,我们深入探讨了RBF内核的复杂性,探讨了它的数学公式、直观理解、实际应用及其在各种机器学习算法中的重要性。
详细介绍及样例数据:https://blog.csdn.net/samLi0620/article/details/144636765
51单片机控制的智能小车.7z
【资源说明】 基于卷积神经网络的数字手势识别安卓APP,识别数字手势0-10详细文档+全部资料+优秀项目+源码.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
python 使用sqlserver必须要这个问题,没办法,只能满世界的找地方下载,终于让我下载到了,现在分享给大家使用
四川采矿场生产安全事故管理制度
简约灰粉共存版_8.0.53.apk
ECharts散点图-全国主要城市空气质量(百度地图)
四川采矿场安全检查管理规定
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于计算机科学与技术等相关专业,更为适合;
空中俯视物体检测9-YOLOv5数据集合集.rar使用YOLO算法从图像中检测对象-V2 2023-05-11 2:51 PM ============================= *与您的团队在计算机视觉项目上合作 *收集和组织图像 *了解和搜索非结构化图像数据 *注释,创建数据集 *导出,训练和部署计算机视觉模型 *使用主动学习随着时间的推移改善数据集 对于最先进的计算机视觉培训笔记本,您可以与此数据集一起使用 该数据集包括1015张图像。 以YOLO V5 PYTORCH格式注释检测对象 - 图像。 将以下预处理应用于每个图像: *像素数据的自动取向(带有Exif-Arientation剥离) *调整大小为640x640(拉伸) 没有应用图像增强技术。
词云图
Python高分毕设——Python&Opencv手势识别系统(完整源码&自定义UI操作界面&视频教程) Python高分毕设——Python&Opencv手势识别系统(完整源码&自定义UI操作界面&视频教程) 使用了OpenCV的视频采集, 图像色域转换, 颜色通道分割, 高斯滤波, OSTU自动阈值, 凸点检测, 边缘检测, 余弦定理计算手势等功能. 准备工作 安装 Python-OpenCV 库 pip install opencv-python -i https://mirrors.ustc.edu.cn/pypi/web/simple 利用 -i 为pip指令镜像源, 这里使用电子科技大学的源, 速度比官方源更快. 安装 Numpy 科学计算库 pip install numpy -i https://mirrors.ustc.edu.cn/pypi/web/simple 安装 PyAutogui 库 pip install pyautogui -i https://mirrors.ustc.edu.cn/pypi/web/simple 代码实现 import nu