java锁的种类

原创 2017年04月09日 08:34:52

1. 可重入锁

当一个线程重新获取锁,读写锁或其他不可重入的同步器时,就可能发生重入锁死。可重入的意思是线程可以重复获得它已经持有的锁。
Java的synchronized块是可重入的。因此下面的代码是没问题的:

(这里提到的锁都是指的不可重入的锁实现,并不是Java类库中的Lock与ReadWriteLock类)

public class Reentrant{
	public synchronized outer(){
		inner();
	}

	public synchronized inner(){
		//do something
	}
}
注意outer()和inner()都声明为synchronized,这在Java中这相当于synchronized(this)块(注:这里两个方法是实例方法,
synchronized的实例方法相当于在this上加锁,如果是static方法,则不然)。如果某个线程调用了outer(),
outer()中的inner()调用是没问题的,因为两个方法都是在同一个管程对象(即this)上同步的。如果一个线程持有某个管程对象上的锁,
那么它就有权访问所有在该管程对象上同步的块。这就叫可重入。若线程已经持有锁,那么它就可以重复访问所有使用该锁的代码块。
下面这个锁的实现是不可重入的:

public class Lock{
	private boolean isLocked = false;
	public synchronized void lock()
		throws InterruptedException{
		while(isLocked){
			wait();
		}
		isLocked = true;
	}

	public synchronized void unlock(){
		isLocked = false;
		notify();
	}
}
如果一个线程在两次调用lock()间没有调用unlock()方法,那么第二次调用lock()就会被阻塞,这就出现了重入锁死。
我们在上面的Lock基础上作一些修改就会变成可重入的锁(这也是可重入锁的基本原理):

public class Lock{
    boolean isLocked = false;
    Thread  lockedBy = null;
    int lockedCount = 0;
    public synchronized void lock()
        throws InterruptedException{
        Thread callingThread = Thread.currentThread();
        while(isLocked && lockedBy != callingThread){
            wait();
        }
        isLocked = true;
        lockedCount++;
        lockedBy = callingThread;
  }
    public synchronized void unlock(){
        if(Thread.curentThread() == this.lockedBy){
            lockedCount--;
            if(lockedCount == 0){
                isLocked = false;
                notify();
            }
        }
    }
}
lockBy:保存已经获得锁实例的线程,在lock()判断调用lock的线程是否已经获得当前锁实例,如果已经获得锁,则直接跳过while,无需等待。
lockCount:记录同一个线程重复对一个锁对象加锁的次数。否则,一次unlock就会解除所有锁,即使这个锁实例已经加锁多次了。
Java中常用的锁的属性
synchronized:可重入锁;
java.util.concurrent.locks.ReentrantLock:可重入锁;

2.自旋锁

自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时 才能进入临界区。如下

public class SpinLock {

  private AtomicReference<Thread> sign =new AtomicReference<>();

  public void lock(){
    Thread current = Thread.currentThread();
    while(!sign .compareAndSet(null, current)){
    }
  }

  public void unlock (){
    Thread current = Thread.currentThread();
    sign .compareAndSet(current, null);
  }
}
使用了CAS原子操作,lock函数将owner设置为当前线程,并且预测原来的值为空。unlock函数将owner设置为null,并且预测值为当前线程。
当有第二个线程调用lock操作时由于owner值不为空,导致循环一直被执行,直至第一个线程调用unlock函数将owner设置为null,
第二个线程才能进入临界区。由于自旋锁只是将当前线程不停地执行循环体,不进行线程状态的改变,所以响应速度更快。
但当线程数不停增加时,性能下降明显,因为每个线程都需要执行,占用CPU时间。
如果线程竞争不激烈,并且保持锁的时间段。适合使用自旋锁。

参考:
http://ifeve.com/reentrance-lockout/
http://ifeve.com/java_lock_see1/
http://www.jianshu.com/p/007bd7029faf


版权声明:本文为博主整理自网络资料,转载请注明!

[Java多线程 五]---JAVA锁有哪些种类

转载自: http://blog.csdn.net/sinat_33087001/article/details/73607625 上一篇既然提到了锁,这一篇来详细介绍JAVA中的锁,也为之后J...
  • nalanmingdian
  • nalanmingdian
  • 2017年09月02日 12:09
  • 532

Java锁类型

转载链接在每个锁类型后边 线程锁类型 1、自旋锁 ,自旋,jvm默认是10次吧,有jvm自己控制。for去争取锁 锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchr...
  • u011514810
  • u011514810
  • 2017年03月07日 14:00
  • 1733

彻底理解ThreadLocal

ThreadLocal是什么 早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁...
  • lufeng20
  • lufeng20
  • 2014年04月22日 16:59
  • 345140

JAVA对象锁与类锁

1、被syncronized修饰的方法,是对类的对象加锁,也就是说,当对象访问该方法时,当前的对象会被加锁,同一时刻同一对象不能再访问该方法,或者该对象的其他被syncronized修饰的方法。不同对...
  • guguituzi
  • guguituzi
  • 2014年11月17日 22:18
  • 1222

java synchronized关键字的用法以及锁的等级:方法锁、对象锁、类锁

作者用通俗易懂的语言将复杂的技术讲解的如此透彻,学习,传播! 原文地址:http://zhh9106.iteye.com/blog/2151791 在java编程中,经常需要用到同步,而用...
  • GS_008
  • GS_008
  • 2016年03月22日 11:15
  • 4354

Java锁的种类以及辨析

Java锁的种类以及辨析 作者:山鸡 锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) 。这...
  • fwt336
  • fwt336
  • 2017年02月09日 17:12
  • 204

java多线程锁种类

锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) 。这些已经写好提供的锁为我们开发提供了便利,但是锁的具体性质以及类...
  • u013322404
  • u013322404
  • 2016年03月01日 14:50
  • 2401

Java中常用的锁分析总结

转:http://blog.csdn.net/lantian0802/article/details/8971552?utm_source=tuicool&utm_medium=referral ...
  • pzasdq
  • pzasdq
  • 2016年11月11日 14:17
  • 1614

java锁的种类以及辨析

转载自: http://ifeve.com/java_lock_see1/  锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLoc...
  • luojinbai
  • luojinbai
  • 2016年05月02日 22:30
  • 1973

java锁的种类

1. 可重入锁 当一个线程重新获取锁,读写锁或其他不可重入的同步器时,就可能发生重入锁死。可重入的意思是线程可以重复获得它已经持有的锁。 Java的synchronized块是可重入的。因此下面的代...
  • John8169
  • John8169
  • 2017年04月09日 08:34
  • 494
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java锁的种类
举报原因:
原因补充:

(最多只允许输入30个字)