同步synchronized和lock区别与利用点

最近研究了一下在多线程同步机制中的两个同步锁synchronized和lock,写一篇文章来记录一下心得:

    首先,synchronized和lock都是同步锁,他们都是在线程的基础上利用的,那么什么是线程呢,线程是程序执行流的最小单元,也就是说,当你在运行一个java程序时,你所做的所有操作都是由线程来实现的,而锁呢,则是在有多个线程同时访问一个数据时,比如多个线程同时访问一个hashmap,同时对map执行了set操作,也就是说多个线程同时向map中存数据,这时就会发生脏数据或不可预料的情况,而我们要对这种情况进行处理,于是我们就想出了一个方法,那就是当线程运行到这一步操作时,我们让这些线程依次进行操作,这也就有效的避免了脏数据的问题,而如何让他们依次操作呢,那就是同步锁了。

    同步锁是面对高并发,高访问量的程序最基础的处理方式,而我们常用的就是synchorinzed和lock这两种方式对需要同步的代码进行加锁。

    我在学校的时候学习java基础的时候,老师就告诉我们hashmap是不安全的,hashtable是安全的,虽然我一直都知道,但是不明白其中的原理,而通过学习,我了解到hashmap与hashtable的区别,主要就是是否加了同步锁。

    其实锁很好明白,最直观的就是一个屋子的门,如果没有加锁,那么谁(线程)都可以进,当多个人一块进的时候,你也不知道到底发生了啥,而我们就是要给这个门加一把锁,并且只给他配一把钥匙,这样我们就可以控制进门的总是有且只有一个人,而线程就是人,每个线程想进门,都得先去拿这把钥匙才能进去,而我们要注意其中一点,就是这个屋子和这个小区(类)所有加了锁的屋子只有这一把钥匙,也就是说,当这个小区有两个以上的门加了锁,每次还是只能有一个人进入加锁的屋子,而没有加锁的,就和平时一样都可以进,这就是hashtable的同步方式,synchorinized,其实这种方式在线程竞争激烈的系统中十分不提倡,因为你想呀,当一个线程占用锁的时候,其它想操作的线程都会被阻塞,所以java在current包下实现了另一种的key-value的安全的存储结构,也就是concurrenthashmap,这个类和hashtable不同,它的加锁方式和底层的实现都异于hashmap和hashtable。

    我们都知道,hashmap的底层是由entry数组组成的链表,每一个entry数组保存一个key-value结构,所有线程都能访问这个链表上任意位置,而concurrenthashmap的底层则是由两个数组构成,也就是segment数组和hashentry数组,这个segment就是concurrenthashmap线程安全的核心,它利用current包下的lock锁的方式,给每一个hashentry都加了锁,也就是说明当多个线程同时访问segment的多个hashentry时,线程是不会有被阻塞的,只有当它们同时访问一个hashentry时才会被阻塞,这样就大大提高了性能,也更适合多线程的环境。


    通过上面的描述我们大体了解了一下同步锁以及两种锁的机制,下面就说一下两种锁的区别:

1)synchronized锁是关键字,作用在jvm层面上而lock是一个接口类作用在类的层次上,简而言之synchronized是java的一个特性,而lock则是jdkcurrent下的一个作用类

2)synchronized是非公平锁,而lock则是公平锁,简单的说当有多个线程同时等待一个锁时,lock是按照等待的时间来获取锁,而synchronized则不是。

3)synchronized放弃锁只有两种情况:①线程执行完了同步代码块的内容②发生异常;而lock不同,它可以设定超时时间,也就是说他可以在获取锁时便设定超时时间,如果在你设定的时间内它还没有获取到锁,那么它会放弃获取锁然后响应放弃操作。

4)synchronized不能够知道线程是否已经获取到锁,但是lock可以知道。

5)synchronized在对一个代码块加锁时不能对于读操作和写操作进行分离,但是lock可以,简单说如果两个线程同时要读取一个代码块的内容,synchronized只能一个线程执行完归还锁,下一个线程才能执行,而lock不一样,lock可以使这两个锁同时进行读操作。


这么一说大体你就能知道这两种锁的应用性,我也大体做一个总结:

1)在少量同步的系统中,适合利用synchronized关键字来进行同步

2)在大量同步及高并发的系统中则适合利用lock锁来进行同步。

完。

你可能感兴趣的:(java性能)