[网络开发]同步与线程安全方案

方案:synchronized,volatile+CAS(compareAndSet),atomic包,Lock接口

java同步和IO同步的对比:

都是同步异步的方案问题,一个操作的是java代码(实际是堆和方法区),一个操作的是TCP RecvBuffer而已

 

线程安全方案:

https://www.cnblogs.com/jianmianruxin/p/7583262.html
---------------------
原文:https://blog.csdn.net/u010287873/article/details/82387494

 http://blog.csdn.net/yangcheng33/article/details/47708631                                                      

                                                               线程安全实现方案 

线程不安全的原因是:多个线程使用线程共享数据时不能保证更新操作的原子性。

线程安全策略:

一:互斥同步

       这是一种悲观同步方案,互斥同步要求使用共享资源的线程必须满足对共享数据的访问具备原子性。如果该线程没有完全结束对共享数据的访问,其他线程不得访问共享数据。

       互斥同步的实现方式有synchronized和ReentrantLock两种方式:

前者获取锁的过程中获取不到时线程会被放入队列陷入阻塞等待。后者可以提供非阻塞获取锁的方式,比如trylock和interruptibly。

       synchronized既可以修饰实例方法也可以修饰类方法,也可以作为同步块。

1.某个线程获取到对象锁时,这个对象的所有被synchronized修饰的同步方法将被此线程锁住,其他线程只能访问此对象的非synchronized方法。

2.每个对象都有锁,一个对象被一个线程上锁,不影响同属一个类的其他实例对象的锁状态,其他线程可以访问另一个实例对象的非同步方法。

3.synchronized修饰类方法时:同步类方法被执行时所有对象的锁状态变为1,所有对象被上锁。

        ReentrantLock跟synchronized相比还包括了中断锁等候和定时锁等候,当线程A先获得了对象锁,线程B在指定时间内无法获取锁时可以自动放弃等待该锁。

ReentrantLock使用代码实现,系统无法自动释放锁,需要在代码中finally子句中显式释放锁lock.unlock();
Lock lock  = new ReentrantLock();
lock.lock();
try{ //可能会出现线程安全的操作 }finally{ //一定在finally中释放锁 //也不能把获取锁在try中进行,因为有可能在获取锁的时候抛出异常 lock.ublock(); }
ReentranLock的API:
  • void lock() 获取锁,调用该方法当前线程将会获取锁,当锁获取后,该方法将返回。获取不到会一直获取,因此此方法是阻塞的。
  • boolean tryLock() 尝试非阻塞的获取锁,调用该方法立即返回,true表示获取到锁
  • boolean tryLock(long time,TimeUnit unit) throws InterruptedException 和tryLock()方法是类似的,只不过区别在于这个方法在拿不到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false
  • void lockInterruptibly() throws InterruptedException 可中断获取锁,与lock()方法不同之处在于该方法会响应中断,即在锁的获取过程中可以中断当前线程
  • 当一个线程获取了锁之后,是不会被interrupt()方法中断的。interrupt()方法不能中断正在运行过程中的线程,线程处于阻塞状态才可被中断(如线程调用了sleep,join,wait方法等),但线程获取锁的过程中不可被中断(除了上面新学的方法lockInterruptibly)。线程中断只能。
  • Thread.interrupt()方法不会中断一个正在运行的线程。它的作用是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。

    interrupt方法并不是强制终止线程,它只能设置线程的interrupted状态,被block的线程(sleep() or join())在被调用interrupt时会产生InterruptException(lock是不会的,直到获取到锁才会去处理中断标志),此时是否终止线程由本线程自己决定

  • 说白了线程的中断方法的作用并不是中断线程,而是把已经阻塞的线程的中断标志改为true(起作用的基本条件是阻塞),但这个标志不一定立即起作用,lockInterruptibly会立即处理该标志,但lock()方法直到获取到了锁才会处理中断标志。
  • void unlock() 释放锁
 ReentrantLock是Lock接口一种常见的实现,它是支持重进入的锁即表示该锁能够支持一个线程对资源的重复加锁。该锁还支持获取锁时的公平与非公平的选择。 
关于锁的重进入,其实synchronized关键字也支持。如前所述,synchronized关键字也是隐式的支持重进入而对于ReentrantLock而言,对于已经获取到锁的线程,再次调用lock()方法时依然可以获取锁而不被阻塞。

synchronized和ReentrantLock都是可重入锁,可重入性在我看来实际上表明了锁的分配机制:基于线程的分配,而不是基于方法调用的分配。举个简单的例子,当一个线程执行到某个synchronized方法时,比如说method1,而在method1中会调用另外一个synchronized方法method2,此时线程不必重新去申请锁,而是可以直接执行方法method2。

  看下面这段代码就明白了:

1
2
3
4
5
6
7
8
9
class MyClass {
    public synchronized void method1() {
        method2();
    }
     
    public synchronized void method2() {
         
    }
}

   上述代码中的两个方法method1和method2都用synchronized修饰了,假如某一时刻,线程A执行到了method1,此时线程A获取了这个对象的锁,而由于method2也是synchronized方法,假如synchronized不具备可重入性,此时线程A需要重新申请锁。但是这就会造成一个问题,因为线程A已经持有了该对象的锁,而又在申请获取该对象的锁,这样就会线程A一直等待永远不会获取到的锁。

  而由于synchronized和Lock都具备可重入性,所以不会发生上述现象。

刚刚提到的公平获取锁与非公平获取锁。如果在绝对时间上,先对于锁进行获取的请求一定先被满足,那么这个锁就是公平的,反之就是非公平的。公平的获取锁也就是等待时间最久的线程优先获取到锁。ReentrantLock的构造函数来控制是否为公平锁。

我在第一次了解到公平获取锁与非公平获取锁的时候,第一反应是公平获取锁的效率高,应该使用公平获取锁。但实际的情况是,非公平获取锁的效率远远大于公平获取锁。

 

java的线程是映射到操作系统的原生线程之上的,如果要阻塞或唤醒一个线程都需要操作系统来帮忙完成,因此需要从用户态切换到内核态。对于代码简单的同步块,状态转换消耗的时间可能比代码执行的时间还要长。因此重量级的synchronized除非有必要否则不使用。API中ReentrantLock和synchronized一样是互斥的方案,一样是可重入的,但多了一些高级功能如可中断,公平锁及锁可以绑定条件等。

二:非阻塞同步

三:可重入代码

如果一段代码的执行结果是可预测的,并且输入相同的数据会得到相同的数据,那么这段代码就是可重入代码,当然也是线程安全的。

 

 

                                                             用户态与内核态的切换

内核态: CPU可以访问内存所有数据, 包括外围设备, 例如硬盘, 网卡. CPU也可以将自己从一个程序切换到另一个程序

用户态: 只能受限的访问内存, 且不允许访问外围设备. 占用CPU的能力被剥夺, CPU资源可以被其他程序获取

为什么要有用户态和内核态

由于需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络, CPU划分出两个权限等级 -- 用户态 和 内核态

所有用户程序都是运行在用户态的, 但是有时候程序确实需要做一些内核态的事情, 例如从硬盘读取数据, 或者从键盘获取输入等. 而唯一可以做这些事情的就是操作系统, 所以此时程序就需要先操作系统请求以程序的名义来执行这些操作.

这时需要一个这样的机制: 用户态程序切换到内核态, 但是不能控制在内核态中执行的指令

这种机制叫系统调用, 在CPU中的实现称之为陷阱指令(Trap Instruction)

他们的工作流程如下:

  1. 用户态程序将一些数据值放在寄存器中, 或者使用参数创建一个堆栈(stack frame), 以此表明需要操作系统提供的服务.
  2. 用户态程序执行陷阱指令
  3. CPU切换到内核态, 并跳到位于内存指定位置的指令, 这些指令是操作系统的一部分, 他们具有内存保护, 不可被用户态程序访问
  4. 这些指令称之为陷阱(trap)或者系统调用处理器(system call handler). 他们会读取程序放入内存的数据参数, 并执行程序请求的服务
  5. 系统调用完成后, 操作系统会重置CPU为用户态并返回系统调用的结果
新生的小心情

 

转载于:https://www.cnblogs.com/PrestonL/p/9938705.html

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

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

相关文章

[css] 说下你对background-size的理解,它有什么运用场景?

[css] 说下你对background-size的理解,它有什么运用场景? 设置背景图的大小,一般用来设置背景图的大小。个人简介 我是歌谣,欢迎和大家一起交流前后端知识。放弃很容易, 但坚持一定很酷。欢迎大家一起讨论 主目录 …

idea的plugins无法使用marketplace plugins are not loaded

idea64.exe.vmoptions删除-Djsse.enableSNIExtensionfalse 再次重启后就可以正常使用plugins!!!

redis实践的一点思路,关于支付回调

大家好,我是烤鸭: 如果作为第三方支付平台,需要通知调用方付款成功。但是出现通知失败的情况,怎么处理。 支付宝的异步通知,每个订单的异步通知实行分频率发送:15s 3m 10m 30m 30m 1h 2h 6h 15h。 如果没有收到success&a…

断电启动+智能插座 七彩虹B460主板实现电脑远程开机

BIOS设置操作步骤: 1,开机按F2进入BIOS系统(小提示:不同的主板按键不一样,开机应该有提示) 2,高级模式 > 高级 > 电源管理设置 > 交流电源恢复后处理 > 选择“开机” 3&#xff0c…

[css] 如何自定义radio按钮的样式

[css] 如何自定义radio按钮的样式 选择器 input[type“radio”]现在几乎不用原生的radio,一是原生样式改成设计稿的样子太浪费时间,二是不同浏览器对于原生radio的展示还不一样。基于状态驱动的思想,用自定义按钮或其他元素来替代radio&…

myabtis 数字+逗号 传参问题 $和#

大家好,我是烤鸭: 遇到一个maybatis传参的问题。 如果传参是数字逗号的形式,比如1,2,3,4,5。 问题复现: 项目中查询sql和navicat查询sql结果不一致。 1 项目中: 如图所示,查到一条数据。 可以看到…

SpringBoot上传文件到本服务器 目录与jar包同级

前言 看标题好像很简单的样子,但是针对使用jar包发布SpringBoot项目就不一样了。 当你使用tomcat发布项目的时候,上传文件存放会变得非常简单,因为你可以随意操作项目路径下的资源。但是当你使用SpringBoot的jar包发布项目的时候,…

JS判断是否是科学计算结果并处理

var re 505899.24- 495991.61- 9907.63;var test1 /\d(?:.(\d*))?e([-]\d)/.test(re);alert("是否是科学计算结果:"test1);var test2 re.toFixed(10)-0;alert("处理后的结果:" test2 );

[css] css怎样使每个字符宽度一样?

[css] css怎样使每个字符宽度一样? 控制字符间距:letter-spacing:1em;[em,px,rem]个人简介 我是歌谣,欢迎和大家一起交流前后端知识。放弃很容易, 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe

大家好,我是烤鸭: 又是采坑实录。 异常如下: org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipeat org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:356)at org.ap…

[css] word-wrap、word-break和white-space有什么区别?

[css] word-wrap、word-break和white-space有什么区别? word-wrap标明是否允许浏览器再单词内进行断句normal 只允许在断字点换行 默认值break-word 在长单词或这url地址内部进行换行word-break标明怎么样进行单词内的断句normal 默认值break-all 允许在单词内换行k…

Redis免费客户端 Another Redis DeskTop Manager 下载地址及安装教程

下载及安装教程地址:GitHub - qishibo/AnotherRedisDesktopManager: 🚀🚀🚀A faster, better and more stable redis desktop manager [GUI client], compatible with Linux, Windows, Mac. Whats more, it wont crash when loadi…

[css] 说说你对字母“X“在CSS中有什么作用?

[css] 说说你对字母"X"在CSS中有什么作用? 可以用作关闭按钮叉叉X的底部与文本对齐的基线位置相同个人简介 我是歌谣,欢迎和大家一起交流前后端知识。放弃很容易, 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面…

JavaScript文字转图片

非常感谢这位博主提供的代码,以下只做代码记录 博文转载地址:https://blog.csdn.net/qq_30100043/article/details/76549377//绘制文字到canvas,判断换行位置,和设置canvas高度 function canvasWrapText(options) {var settings …

mysql 内置功能 函数 date_format函数

创建数据库db12 create database db12 charsetutf8; use db12; 准备表和记录 CREATE TABLE blog (id INT PRIMARY KEY auto_increment,NAME CHAR (32),sub_time datetime ); 插入记录 INSERT INTO blog (NAME, sub_time) VALUES(第1篇,2015-03-01 11:31:21),(第2篇,2015-03-11 …

低版本webview无法请求jquery ajax

大家好,我是烤鸭: 又来踩坑了。 1. 场景复现 有反馈我们的H5页面,无法正确显示页面。就类似下图这样,ajax没法请求到数据。 之前测试的时候是在web端做的测试,用安卓7.0和8.0的手机都试了一下,是没…

[css] CSS3中的transition是否可以过渡opacity和display?

[css] CSS3中的transition是否可以过渡opacity和display? transition过渡display是有一个前提条件: 浏览器渲染是在每一帧的最后,每一帧都会执行以下操作:js执行2.style加持3.layout4.paint5.composite在js执行过程中, 遇到DOM操作&#xff…

Ubuntu 无法应用原保存的显示器配置

Ubuntu开机之后页面出现:无法应用原保存的显示器配置所选模式均不匹配可能的模式:为 CRTC 63 尝试模式CRTC 63:尝试 800x60060Hz 模式输出在 1366x76860Hz (通过 0)CRTC 63:尝试 2560x160060Hz 模式输出在 1366x76860Hz (通过 0)C…

由excel导出引起的cpu 100% 和gc 的问题

大家好,我是烤鸭: 记一次 由excel导出 导致的cpu飙升200%,jvm 内存不足。 1. 场景复现 前端页面导出Excel,之前导出4,5W条数据都没什么问题的。 今天业务突然反馈说导出不了了,我试着导出了2w数据&#xff0…

[css] 说下background-color:transparent和opacity:0的区别是什么?

[css] 说下background-color:transparent和opacity:0的区别是什么? background-color:transparent: 只是把背景色设置为透明,并不会影响元素中的内容。可以利用 transparent 进行三角、扇形的设置。opacity: 0: 会影响整个元素,元素的内容也会…