文档章节

Java可重入锁学习笔记

M
 MackCC_Sun
发布于 2016/07/12 10:43
字数 1026
阅读 44
收藏 2

目录

  1. 什么是可重入锁
  2. 为什么要可重入
  3. 如何实现可重入锁
  4. 有不可重入锁吗
  5. demo代码展示
  6. 参考文章

1 . 什么是可重入锁

锁的概念就不用多解释了,当某个线程A已经持有了一个锁,当线程B尝试进入被这个锁保护的代码段的时候.就会被阻塞.而锁的操作粒度是”线程”,而不是调用(至于为什么要这样,下面解释).同一个线程再次进入同步代码的时候.可以使用自己已经获取到的锁,这就是可重入锁
java里面内置锁(synchronize)和Lock(ReentrantLock)都是可重入的

2 . 为什么要可重入

如果线程A继续再次获得这个锁呢?比如一个方法是synchronized,递归调用自己,那么第一次已经获得了锁,第二次调用的时候还能进入吗? 直观上当然需要能进入.这就要求必须是可重入的.可重入锁又叫做递归锁,再举个例子.

1
2
3
4
5
6
7
8
9
10
11
12
public class Widget {
        public synchronized void doSomething() {
            ...
        }
}
     
public class LoggingWidget extends Widget {
        public synchronized void doSomething() {
            System.out.println(toString() + ": calling doSomething");
            super.doSomething();//若内置锁是不可重入的,则发生死锁
        }
}

这个例子是java并发编程实战中的例 子.synchronized 是父类Widget的内置锁,当执行子 类的方法的时候,先获取了一次Widget的锁,然后在执行super的时候,就要获取一次,如果不可重入,那么就跪了.

3 . 如何实现可重入锁

为每个锁关联一个获取计数器和一个所有者线程,当计数值为0的时候,这个所就没有被任何线程只有.当线程请求一个未被持有的锁时,JVM将记下锁的持有者,并且将获取计数值置为1,如果同一个线程再次获取这个锁,技术值将递增,退出一次同步代码块,计算值递减,当计数值为0时,这个锁就被释放.
ReentrantLock里面有实现

4 . 有不可重入锁吗

这个还真有.Linux下的pthread_mutex_t锁是默认是非递归的。可以通过设置PTHREAD_MUTEX_RECURSIVE属性,将pthread_mutex_t锁设置为递归锁。如果要自己实现不可重入锁,同可重入锁,这个计数器只能为1.或者0,再次进入的时候,发现已经是1了,就进行阻塞.jdk里面没有默认的实现类.

5 . demo代码展示

5.1 内置锁的可重入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ReentrantTest {
    public void method1() {
        synchronized (ReentrantTest.class) {
            System.out.println("方法1获得ReentrantTest的内置锁运行了");
            method2();
        }
    }

    public void method2() {
        synchronized (ReentrantTest.class) {
            System.out.println("方法1里面调用的方法2重入内置锁,也正常运行了");
        }
    }

    public static void main(String[] args) {
        new ReentrantTest().method1();
    }
}

 

5.2 lock对象的可重入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockTest {
    private Lock lock = new ReentrantLock();

    public void method1() {
        lock.lock();
        try {
            System.out.println("方法1获得ReentrantLock锁运行了");
            method2();
        } finally {
            lock.unlock();
        }
    }

    public void method2() {
        lock.lock();
        try {
            System.out.println("方法1里面调用的方法2重入ReentrantLock锁,也正常运行了");
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        new ReentrantLockTest().method1();
    }
}

 

5.3 不同线程不可访问同一锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantTwoThreadTest {
    private static Lock lock = new ReentrantLock();

    private static class T1 extends Thread {
        @Override
        public void run() {
            System.out.println("线程1启动");
            lock.lock();
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
            System.out.println("线程2终止");
        }
    }

    private static class T2 extends Thread {
        @Override
        public void run() {
            System.out.println("线程2启动");
            lock.lock();
            lock.unlock();
            System.out.println("线程2终止");
        }
    }


    public static void main(String[] args) {
        new T1().start();
		Thread.sleep(100);
        new T2().start();
    }
}

6. 参考文章

  1. 可重入锁测试
  2. 生产者消费者的一个更真实的例子
  3. 浅谈Java中的锁
  4. java并发编程实战

本文转载自:http://leaver.me/2015/11/20/Java%E5%8F%AF%E9%87%8D%E5%85%A5%E9%94%81%E5%AD%A6%E4%B9%A0%E7%AC%94%E...

共有 人打赏支持
M
粉丝 3
博文 158
码字总数 29095
作品 0
朝阳
技术主管
私信 提问
加载中

评论(1)

wen6688
wen6688
看机会吗?加我微信吧282507421
美团猫眼团队面试题:Maven+OSGi+Spring+Zookeeper+Dubb

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/t4i2b10X4c22nF6A/article/details/84327220 交叉一面 concurrent包下面用过哪些? countdownlatch功能实现 ...

JAVA高级架构v
11/21
0
0
Java锁的种类以及辨析(四):可重入锁

作者:山鸡 锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) 。这些已经写好提供的锁为我们开发提供了便利,但是锁的具体性质以及类型...

onedotdot
2017/11/01
0
0
读书笔记之《Java并发编程的艺术》-java中的锁

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
0
【Java并发性和多线程】Java中的锁

本文为转载学习 原文链接:http://ifeve.com/locks/ 锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂。因为锁(以及其它更高级的线程同步机制)是由...

heroShane
2014/02/02
0
0
轻松学习java可重入锁(ReentrantLock)的实现原理

前言 相信学过java的人都知道 synchronized 这个关键词,也知道它用于控制多线程对并发资源的安全访问,兴许,你还用过Lock相关的功能,但你可能从来没有想过java中的锁底层的机制是怎么实现...

onedotdot
2017/10/31
0
0

没有更多内容

加载失败,请刷新页面

加载更多

迭代器模式 Iterator 行为型 设计模式(二十)

  在计算机中,Iterator意为迭代器,迭代有重复的含义,在程序中,更有“遍历”的含义      如果给定一个数组,我们可以通过for循环来遍历这个数组,这种遍历就叫做迭代      对于...

SEOwhywhy
10分钟前
0
0
【 58沈剑 架构师之路】InnoDB,5项最佳实践,知其所以然

缓存讲了一个月《缓存架构,一篇足够》。今天,开始写数据库。 第一篇,说说MySQL两个最常用的存储引擎,MyISAM和InnoDB。照自己的理解,把一些知识点总结出来,不只说知识点,多讲“为什么”...

张锦飞
12分钟前
0
0
windows10小鹤双拼注册表

《安全第一》直接发文本内容,自己建文本,改文本后缀reg。 使用方法: 1.复制下示文本内容,打开你的文本编辑器(#记事本notepad或其他++),粘贴文本内容并保存在任意位置(不影响使用) ...

漫步海边小路
19分钟前
1
0
一、数据挖掘

数据挖掘的发展动力---需要是发明之母 数据爆炸问题 自动数据收集工具和成熟的数据库技术使得大量的数据被收集,存储在数据库、数据仓库或其他信息库中以待分析。我们拥有丰富的数据,但却缺...

凯文加内特
22分钟前
1
0
Java线程池ThreadPoolExecutor

线程池 ThreadPoolExecutor 线程池是ExecutorService的实现,可以通过Executors执行工厂构造不同类型的执行服务(线程池)。 ThreadPoolExecutor线程池使用的是阻塞队列BlockingQueue。 用于...

器石_
23分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部