Java中的线程安全和非线程安全以及锁的几个知识点
1. 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。
线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是“脏”数据。
比方说ArrayList是非线程安全的,Vector是线程安全的;HashMap是非线程安全的,HashVector是线程安全的;StringBuilder是非线程安全的,StringBuffer是线程安全的。
2. 线程安全是通过线程同步来控制的,也就是synchronized关键字,因此会导致性能的降低,所以使用的时候如果是多个线程操作一个对象,那么就使用线程安全的Vector,否则就使用效率更高的ArrayList。
需要注意的是非线程安全并不等于不安全,因为我如果每个线程都有一个自己的ArrayList,各自不会访问,那么用ArrayList是没有问题的。
3. 锁的几个机制:
1.可重入锁:基于线程分配锁,而不是根据方法的调用来进行分配
class Main
{
public synchronized void method1()
{
method2();
} public synchronized void method2()
{
}
}
假如某一时刻,线程A执行到了method1,此时线程A获取了这个对象的锁,而由于method2也是synchronized方法,假如synchronized不具备可重入性,此时线程A需要重新申请锁。但是这就会造成一个问题,因为线程A已经持有了该对象的锁,而又在申请获取该对象的锁,这样就会线程A一直等待永远不会获取到的锁。
2.可中断锁
如果某一线程A正在执行锁中的代码,另一线程B正在等待获取该锁,可能由于等待时间过长,线程B不想等待了,我们可以让它中断自己或者在别的线程中中断它,这种就是可中断锁。synchronized就不是可中断锁,而Lock是可中断锁。
3.公平锁
尽量以请求锁的顺序来获取锁。比如同是有多个线程在等待一个锁,当这个锁被释放时,等待时间最久的线程(最先请求的线程)会获得该所,这种就是公平锁。相对的就有非公平锁,如synchronized就是非公平锁
4. 了解一下Synchronized
大致的描述一下,个人感觉被Synchronized修饰的线程或者代码块,就只能一个人单独访问,其他人想访问就必须等到找个人使用完交给下一个人。这样的好处就是对于很多线程共用的一些变量不会出现几个线程同时在修改它,比方说我们的临界区元素和变量。它的最大的特征就是在同一时刻只有一个线程能够获得对象的监视器,从而进入到同步代码块或者同步方法之中。
但是这样也会有一个问题,打个比方,我们在购物的时候排队,大家要是都到结账的时候才从钱包掏钱就不如自己先把自己的付款二维码准备好的效率快,就是使用Synchronized修饰的话运行时候效率会变低,这个时候我们可以了解下一个知识点:悲观锁和乐观锁。
1.悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。Synchronized就是悲观锁。
2.乐观锁:总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。但是这样会有一个问题就是可能会出现冲突,就是你假设归你假设,别人不一定这么乖。所以我们利用版本号和CAS操作来实现这个。
CAS设计到三个操作数::V 内存地址存放的实际值;O 预期的值(旧值);N 更新的新值。当V和O相同时,也就是说旧值和内存中实际的值相同表明该值没有被其他线程更改过,即该旧值O就是目前来说最新的值了,自然而然可以将新值N赋值给V。反之,V和O不相同,表明该值已经被其他线程改过了则该旧值O不是最新版本的值了,所以不能将新值N赋给V,返回V即可。所以多个线程同时访问的时候就只会有一个线程成功。
实例理解一下:
比方说在内存地址V中,存放着值为10的变量,此时此时线程1想要把变量的值增加1。对线程1来说,旧的预期值A=10,要修改的新值B=11。在线程1要提交更新之前,另一个线程2抢先一步,把内存地址V中的变量值率先更新成了11。线程1开始提交更新,首先进行A和地址V的实际值比较(Compare),发现A不等于V的实际值,提交失败。线程1重新获取内存地址V的当前值,并重新计算想要修改的新值。此时对线程1来说,A=11,B=12。这个重新尝试的过程被称为自旋。这一次比较幸运,没有其他线程改变地址V的值。线程1进行Compare,发现A和地址V的实际值是相等的。线程1进行SWAP,把地址V的值替换为B,也就是12。
3.那么这两种锁应用场景:乐观锁的话简单的来说CAS适用于写比较少的情况下(多读场景,冲突一般较少),悲观锁如synchronized适用于写比较多的情况下(多写场景,冲突一般较多)
5. 上锁的话除了synchronized还要Lock操作
1.synchronized的缺点:当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁,并且等待的线程是不能做其他事情的,会影响执行的效率。通过Lock可以让等待的进程一直等待下去。
2.Lock的几种方法:lock()方法是平常使用得最多的一个方法,就是用来获取锁;tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。unlock()释放锁,我们应该把释放锁的操作放在finally块中进行保证锁一定会被释放防止死锁的事情发生。
3.Lock和Synchronized的区别:
Lock不是Java语言内置的是一个接口,synchronized是Java语言的关键字,所以synchronized不需要用户去手动释放锁但是Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。
Lock可以让等待锁的线程响应中断,而synchronized却不行。
通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
Lock可以提高多个线程进行读操作的效率。
Java中的线程安全和非线程安全以及锁的几个知识点的更多相关文章
- JAVA中的线程安全与非线程安全
原文:http://blog.csdn.net/xiao__gui/article/details/8934832 ArrayList和Vector有什么区别?HashMap和HashTable有什么 ...
- 为什么JAVA虚拟机分为线程共享和非线程共享?
大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区) ,Heap(堆) , Program Counter Register(程序计数器) , VM Stack(虚拟 ...
- Java基础-Java中的并法库之线程池技术
Java基础-Java中的并法库之线程池技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是线程池技术 二.
- Java线程安全和非线程安全
ArrayList是非线程安全的,Vector是线程安全的:HashMap是非线程安全的,HashTable是线程安全的:StringBuilder是非线程安全的,StringBuffer是线程安全的 ...
- 转:Windows下的PHP开发环境搭建——PHP线程安全与非线程安全、Apache版本选择,及详解五种运行模式。
原文来自于:http://www.ituring.com.cn/article/128439 Windows下的PHP开发环境搭建——PHP线程安全与非线程安全.Apache版本选择,及详解五种运行模 ...
- (转)PHP线程安全与非线程安全的区别:如何选择用哪一个?
PHP线程安全与非线程安全的区别:如何选择用哪一个? 很多时候,我们在做PHP环境配置的时候,很多人都是直接去乱下载PHP版本的,但是他不清楚:从2000年10月20日发布的第一个Windows版的P ...
- 浅谈Java中静态初始化块跟非初始化块
众所周知在JAVA编程语言中有两种初始化块: 静态初始化块 非静态初始化块 他们到底有什么区别呢?今天就浅谈一下JAVA中静态初始化块和非静态初始化块的区别 静态初始化块 定义: ...
- Java中的参数验证(非Spring版)
1. Java中的参数验证(非Spring版) 1.1. 前言 为什么我总遇到这种非正常问题,我们知道很多时候我们的参数校验都是放在controller层的传入参数进行校验,我们常用的校验方式就是引入 ...
- java中线程安全和非线程安全的集合
线程安全 非线程安全 Collection Vector ArrayList.LinkedList HashSet.TreeSet Map HashTable HashMap.TreeMap 字符串 ...
随机推荐
- Codeforces626B - Cards【模拟】
题意: 两张相同可以合并成相同: 两张不同可以产生另外一个不同: 求最终的可能颜色: 思路: 模拟啊. 总共也就那么几种情况,具体看挫code--. #include<iostream> ...
- bzoj 1814: Ural 1519 Formula 1【插头dp】
设f[i][j][s]为轮廓线推到格子(i,j),状态为s的方案数 括号表示一段线的左端和右端,表示成左括号和右括号,状压的时候用1和2表示,0表示已经闭合 下面的蓝线是黄色格子的轮廓线,dp转移要把 ...
- poj 2960 S-Nim【SG函数】
预处理出SG函数,然后像普通nim一样做即可 #include<iostream> #include<cstdio> using namespace std; const in ...
- jQuery 第九章 工具方法
$.type() $.isArray() $.isFunction() $.isWindow()... $.trim() $.proxy() $.noConflict() $.each() $.map ...
- 开发者神器!Windows上最强大的虚拟桌面工具-Dexpot
简介 : 用过Linux和Mac计算机的人都知道 , 这两个系统上都有个多桌面的功能非常使用 . 而在Windows上并没有该项功能 , 虽然目前Win10已经增加了多桌面的程序 , 但使用上仍体验不 ...
- iOS 获取类的字符串名称 Swift4
以下实例基于Swift4,且在class, struct, enum中都可用: class Foo { // 实例属性中指定明确的类名来获取名称 var typeName: String { ...
- 利用VS自带的dotfuscator混淆代码的学习
对于一些原创的敏感代码,我们可以通过简单的重命名混淆使得别人难以真正理解执行原理.这一点,使用VS自带的dotfuscator即可实现. 如上图所示,你可以自定义选择哪些类被排除重命名,内置的规则中, ...
- python正则表达式提取中文
import urllib.requestimport reurl='https://songsearch.kugou.com/song_search_v2?callback=jQuery112407 ...
- Chrome下font-size小于12px的解决办法
自从Chorme取消了-webkit-text-size-adjust,这个问题又变得令人烦恼起来. 好在我们可以利用-webkit-transform这个私有属性. .box{ -webkit-tr ...
- CentOS Linux下MySQL 5.1.x的安装、优化和安全配置
下载页面:http://dev.mysql.com/downloads/mysql/5.1.html#downloads 到页面底部,找到Source downloads,这个是源码版本,下载第1个T ...