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中的线程安全和非线程安全以及锁的几个知识点的更多相关文章

  1. JAVA中的线程安全与非线程安全

    原文:http://blog.csdn.net/xiao__gui/article/details/8934832 ArrayList和Vector有什么区别?HashMap和HashTable有什么 ...

  2. 为什么JAVA虚拟机分为线程共享和非线程共享?

    大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区) ,Heap(堆) , Program Counter Register(程序计数器) , VM Stack(虚拟 ...

  3. Java基础-Java中的并法库之线程池技术

    Java基础-Java中的并法库之线程池技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是线程池技术 二.

  4. Java线程安全和非线程安全

    ArrayList是非线程安全的,Vector是线程安全的:HashMap是非线程安全的,HashTable是线程安全的:StringBuilder是非线程安全的,StringBuffer是线程安全的 ...

  5. 转:Windows下的PHP开发环境搭建——PHP线程安全与非线程安全、Apache版本选择,及详解五种运行模式。

    原文来自于:http://www.ituring.com.cn/article/128439 Windows下的PHP开发环境搭建——PHP线程安全与非线程安全.Apache版本选择,及详解五种运行模 ...

  6. (转)PHP线程安全与非线程安全的区别:如何选择用哪一个?

    PHP线程安全与非线程安全的区别:如何选择用哪一个? 很多时候,我们在做PHP环境配置的时候,很多人都是直接去乱下载PHP版本的,但是他不清楚:从2000年10月20日发布的第一个Windows版的P ...

  7. 浅谈Java中静态初始化块跟非初始化块

    众所周知在JAVA编程语言中有两种初始化块:   静态初始化块 非静态初始化块 他们到底有什么区别呢?今天就浅谈一下JAVA中静态初始化块和非静态初始化块的区别   静态初始化块 定义:       ...

  8. Java中的参数验证(非Spring版)

    1. Java中的参数验证(非Spring版) 1.1. 前言 为什么我总遇到这种非正常问题,我们知道很多时候我们的参数校验都是放在controller层的传入参数进行校验,我们常用的校验方式就是引入 ...

  9. java中线程安全和非线程安全的集合

    线程安全 非线程安全 Collection Vector ArrayList.LinkedList HashSet.TreeSet Map HashTable HashMap.TreeMap 字符串 ...

随机推荐

  1. POJ3264【线段树】

    求区间最值-(基础,继续) code---.. #include<cstdio> #include<iostream> #include<string.h> #in ...

  2. web前端图片预加载

    是什么? 浏览器会缓存静态资源(hmtl/css/img等).图片预加载就是让浏览器提前缓存图片,提升用户体验. 浏览器什么情况下会下载图片? 1,解析到html中img的src属性的时候 2,解析到 ...

  3. yield 为什么不能进入回调函数

    操他妈的, allowed_domains = ['voice.hupu.com'] 这里面必须是域名,而不能是个路径,遇见问题不要瞎几把想,及时Google才是正道!!!!!!!!!11 感谢: h ...

  4. UIImageView 使图片圆形的方法

    UIImageView 圆形的两种方法 1.cornerRadius (tableView,collectionView尽量避免使用,影响性能) //想要圆角 cornerRadius必须是 imag ...

  5. 51Nod 1021 石子归并(动态规划)

    #include <iostream> #include <algorithm> #include <string> #include <iostream&g ...

  6. UWP 页面跳转传值

    如果涉及到页面跳转,一般用Frame这个控件来管理不同的页面. <Grid Name="RootGrid"> <Frame Name="RootFram ...

  7. Dima and Magic Guitar CodeForces - 366E

    Dima and Magic Guitar CodeForces - 366E 题意: http://blog.csdn.net/u011026968/article/details/38716425 ...

  8. Planning CodeForces - 854C

    Planning CodeForces - 854C 题意:有n架航班,第i架原先的时候是在第i分钟起飞的.现在前k分钟无法有飞机起飞,因此需要调整安排表,延后飞机起飞.仍然要求每一分钟只有一架飞机起 ...

  9. PopupWindow(2)简单示例-自定义弹出菜单

    本示例,用 popupWindow 自定义弹出菜单 public class CustomActionProvider extends ActionProvider implements OnMenu ...

  10. fgetcsv()函数

    fgetcsv()函数.fgetcsv()函数可以读取指定文件的当前行,使用CSV格式解析出字段,并返回一个包含这些字段的数组.语法格式如下:array fgetcsv(resource $handl ...