Java中的锁不管是Lock还是synchronized都可以分为互斥锁和非互斥锁。

  互斥锁只能被一个线程持有,其他线程只能等待锁的释放。synchronized,ReentrantLock,ReadWriteReentrantLock的WriteLock是互斥的,但ReadLock不是互斥的。

  FileLock可以设置为互斥锁或者非互斥锁。

  实现锁时可以基于操作系统的调度,也可以以自旋的形式来实现。

  利用操作系统的指令,让线程等待,当锁可用时,让线程醒过来。这种适合需要等待长时间的。如果等待的时间短,这个操作的代价是较大的。

  用循环不断的轮询锁的状态,锁可用的时候就退出。这就是自旋锁。这样里面基本不做什么事情的循环是非常耗CPU的,如果等待锁的时间很长,用这种方式是不合适的。

  自旋锁是JVM实现的,下面的例子可以简单的描述自旋锁

public class MyWaitNotify3{

  MonitorObject myMonitorObject = new MonitorObject();
boolean wasSignalled = false; public void doWait(){
synchronized(myMonitorObject){
while(!wasSignalled){
try{

   } catch(InterruptedException e){...}
}
//clear signal and continue running.
  ...
wasSignalled = false;
}
} public void doNotify(){
synchronized(myMonitorObject){
wasSignalled = true;
myMonitorObject.notify();
}
}
}

  没有其他的线程调用doNotify之前,doWait将一直自旋,等待wasSignalled变为true。

  自旋锁的缺点:

  1.自旋锁一直占用CPU,他在未获得锁的情况下,一直运行自旋,所以占用着CPU,如果不能在很短的时 间内获得锁,这无疑会使CPU效率降低。

  2.在用自旋锁时有可能造成死锁,当递归调用时有可能造成死锁。

  可以使用-XX:+UseSpinning来打开自旋锁,使用-XX:PreBlockSpin来设置等自旋待的次数。

  有些时候我们会在完全没必要的情况下用到了锁,可以使用逃逸分析和锁消除来提升系统的性能。

  例如,下面的局部变量StringBuffer完全用不到加锁,反而会影响性能。 

public String createNewString(String a,String b){
StringBuffer sb = new StringBuffer();
return sb.append(a).append(b);
}

  逃逸分析和锁消除可以使用-XX:+DoEscapeAnalysis和-XX:+EliminateLocks。锁消除需要JVM工作在server模式下。

  可重入锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。ReentrantLock 和synchronized 都是可重入锁。  

public class Test implements Runnable{

    public synchronized void get(){
System.out.println(Thread.currentThread().getId());
set();
} public synchronized void set(){
System.out.println(Thread.currentThread().getId());
} @Override
public void run() {
get();
}
public static void main(String[] args) {
Test ss=new Test();
new Thread(ss).start();
new Thread(ss).start();
new Thread(ss).start();
}
}

  独占锁是一种悲观锁,synchronized就是一种独占锁,它假设最坏的情况,并且只有在确保其它线程不会造成干扰的情况下执行,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。而另一个更加有效的锁就是乐观锁。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。

  Atomic类型的数据类型,如AtomicIntegerAtomicLongAtomicReferenceAtomicBoolean等都可使用的是乐观锁。Atomic类型的实现是基于CAS算法的,由于需要同步的地方极少,也被称为轻量级锁。

  分布式系统上还有分布式锁等。

   

  对于多线程来说,死锁是非常严重的系统问题,必须修正。除了死锁,遇到很多的就是活跃度问题了。 活跃度问题主要包括:饥饿,丢失信号,和活锁等。 

  饥饿是指线程需要访问的资源被永久拒绝,以至于不能在继续进行。 比如说:某个权重比较低的线程可能一直不能够抢到CPU周期,从而一直不能够被执行。

  也有一些场景是比较容易理解的。对于一个固定大小的连接池中,如果连接一直被用完,那么过多的任务可能由于一直无法抢占到连接从而不能够被执行。这也是饥饿的一种表现。

  丢失信号比较好理解,thread1因为conditionA被wait,thread2因为conditionB被wait,另一线程调用notify而非notifyAll,thread1被唤醒,实际是conditionB满足了,应该是thread2被唤醒.这样thread1,thread2都无法正常运行。

  

  活锁(Livelock)是指线程虽然没有被阻塞,但是由于某种条件不满足,一直尝试重试,却终是失败。  

  线程间的协同也有可能导致活锁。例如如果两个线程发生了某些条件的碰撞后重新执行,那么如果再次尝试后依然发生了碰撞,长此下去就有可能发生活锁。  

  解决活锁的一种方案是对重试机制引入一些随机性。例如如果检测到冲突,那么就暂停随机的一定时间进行重试。这回大大减少碰撞的可能性。

Java锁概念基础的更多相关文章

  1. Java基础之(一)——从synchronized优化看Java锁概念

    一.悲观锁和乐观锁概念 悲观锁和乐观锁是一种广义的锁概念,Java中没有哪个Lock实现类就叫PessimisticLock或OptimisticLock,而是在数据并发情况下的两种不同处理策略. 针 ...

  2. Java 锁 概念介绍

    一   Java中的锁是什么? /* * 一 Java锁定义? * 在计算机科学中,锁(lock)或互斥(mutex)是一种同步机制,用于在有许多执行线程的环境中强制对资源的访问限制. * 锁旨在强制 ...

  3. Java锁--框架

    根据锁的添加到Java中的时间,Java中的锁,可以分为"同步锁"和"JUC包中的锁". 同步锁 即通过synchronized关键字来进行同步,实现对竞争资源 ...

  4. 【JAVA编码专题】JAVA字符编码系列一:Unicode,GBK,GB2312,UTF-8概念基础

    这两天抽时间又总结/整理了一下各种编码的实际编码方式,和在Java应用中的使用情况,在这里记录下来以便日后参考. 为了构成一个完整的对文字编码的认识和深入把握,以便处理在Java开发过程中遇到的各种问 ...

  5. java锁与监视器概念 为什么wait、notify、notifyAll定义在Object中 多线程中篇(九)

    在Java中,与线程通信相关的几个方法,是定义在Object中的,大家都知道Object是Java中所有类的超类 在Java中,所有的类都是Object,借助于一个统一的形式Object,显然在有些处 ...

  6. JAVA字符编码一:Unicode,GBK,GB2312,UTF-8概念基础

    第一篇:JAVA字符编码系列一:Unicode,GBK,GB2312,UTF-8概念基础 来源:holen'blog   对字符编码与Unicode,ISO 10646,UCS,UTF8,UTF16, ...

  7. java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一)

    目前对于同步,仅仅介绍了一个关键字synchronized,可以用于保证线程同步的原子性.可见性.有序性 对于synchronized关键字,对于静态方法默认是以该类的class对象作为锁,对于实例方 ...

  8. -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中

     本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁  sleep()和wait()方法的区别 为什么wait( ...

  9. Java中的锁概念

    掌握Java中锁是Java多线程编程中绕不开的知识,只有知道理解Java各种锁才能在编码过程中灵活运用,写出更高效的多线程程序.而理解掌握锁的第一步,可从宏观上对比理解一下各种锁概念. 公平锁/非公平 ...

随机推荐

  1. 51 Nod 1027 大数乘法【Java大数乱搞】

    1027 大数乘法 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 给出2个大整数A,B,计算A*B的结果. Input 第1行:大数A 第2行:大数B (A,B的长度  ...

  2. CSS3动画属性和flex弹性布局各个属性

    [CSS3动画的使用] 1.声明一个关键帧(动画): @keynames name{ from{} to{} } 每个阶段的写法: ①可以直接使用from-to的写法 ②可以设置0%-100%的写法, ...

  3. io流读取文件

    package test; import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import ...

  4. 微信小程序实现淡入淡出效果(页面跳转)

    //目前小程序没有fadeIn(),fadeOut()方法所以还是本方法手写  <!--wxml--><!--蒙版(渐出淡去效果)--><view class=" ...

  5. 内核知识第12讲,SSDT表.以用户模式到系统模式的两种方式.

    内核知识第12讲,SSDT表.以用户模式到系统模式的两种方式. 一丶IDT解析. 我们知道.IDT表中存放着各种中断信息.比如当我们调用int 3的时候,则会调用IDT表中的第三项来进行调用. 而函数 ...

  6. C++ 初始化列表(转)

    转载自:http://www.cnblogs.com/graphics/archive/2010/07/04/1770900.html 何谓初始化列表 与其他函数不同,构造函数除了有名字,参数列表和函 ...

  7. DOM解析原理示意

    DOM解析原理示意  

  8. cnzz友盟怎么安装网站统计代码监控网站流量

    做网站的都知道cnzz统计,它是用来统计网站流量的,可以分析网站数据,进行更好的对网站优化,下面我教大家怎么添加统计代码 工具/原料 cnzz 方法/步骤 打开百度搜索"cnzz友盟&quo ...

  9. win7彻底卸载iis

    https://jingyan.baidu.com/article/e5c39bf5829e8e39d660336c.html 昨天在电脑上搭建了PHP开发环境之后,重启apache服务器老是报错,检 ...

  10. 如何完成域名和ip地址的绑定

    首先,我们要知道什么是域名绑定,所谓域名绑定就是是指已选定的域名与服务器主机的空间绑定,实在是在域名注册查询上设置或者WEB服务器上设置,使一个域名被指导向一特定空间,从而使访问者访问你的域名的时候就 ...