`
DiaoCow
  • 浏览: 241575 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Java锁相关总结

    博客分类:
  • Java
 
阅读更多
1.ReentrantLock对象
private ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
     //代码段
}
finally {
     lock.unlock();  // 这步至关重要,千万不能遗漏
}

a.一旦一个线程获得了锁对象,那么其他线程都将阻塞在lock.lock()方法中;

b.锁对象是可重入的(即已经获得锁的线程可以再次获得锁),这时候琐计数+1,当线程调用unlock方法时,琐计数-1,只有当琐计数为0时,才被释放;

c.ReentrantLock类还具有一个带有boolean参数的构造方法,该参数表示是否需要执行公平策略,一个公平锁偏爱等待时间最长的线程(会降低性能),默认是随机选择一个线程获得锁;

2.基于锁的条件变量

a.如何创建一个条件变量?
private ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();

b.如何使用条件变量?
当一个线程获得锁后,发现不具备执行下一步条件时,这时候可以调用condition.await()方法,该方法会导致当前线程释放锁,并且阻塞在当前条件的等待集中;只有当另一个线程调用condition.signalAll()方法或是condition.signal()方法,才能解除阻塞(线程会去重新竞争锁,当再次获得锁后便从await方法返回);

通过条件变量,我们可以简单的实现一个生产者消费者模型(java sdk中代码):
class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newC ondition(); 
   final Condition notEmpty = lock.newCondition(); 

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length)  // 一定要是while循环
         notFull.await();
       items[putptr] = x;
       if (++putptr == items.length) putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }

   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0)
         notEmpty.await();
       Object x = items[takeptr];
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   }
 }


c.signal()方法和singalAll()方法的区别:
signalAll方法激活因为该条件而等待的所有线程,而singal只激活其中一个线程;

3.synchronized关键字
a.java中每一个对象都有一个内部锁,如果一个方法用synchronized关键字声明,那么整个方法将被保护起来:
void synchronized method() {
     // 代码片段
}

等价于
void method {
     this.inner.lock(); 
     try {
          // 代码片段
     } finally {
          this.inner.unlock();
     }
}

b.内部对象锁只有一个条件变量,我们可以通过wait方法将线程放入等待集中,也可以通过notif/notifAll方法唤醒等待集中的线程;

c.在静态方法前加synchronized,这时候获得的锁不是对象的内部锁(因为这时候还没对象),获得是当前类字节码锁,所以
public static synchronized void method1 {
}

public static synchronized void method2 {
}

public synchronized void method3 {
}

public synchronized void method4 {
}

method1和method2线程同步,method3和method4线程同步,其余方法之间没有线程同步






1
10
分享到:
评论
7 楼 vavi 2013-03-06  
while (count == items.length)  // 一定要是while循环   
        notFull.await();  

是因为存在 "spurious wakeup"
6 楼 DiaoCow 2012-07-25  
337240552 写道
总结的不错 不过如果是初学者建议看下java编程思想21章 并发 讲的很详细。

谢谢指导 ^_^
5 楼 DiaoCow 2012-07-25  
tenderuser 写道
 while (count == items.length)  // 一定要是while循环  
         notFull.await();  

这个地方为什么一定要用while循环呢? 为什么不直接使用if判断? 在这之前已经获得锁了,已经可以保证对count的独占了(这里只有put和take方法)。。


是这样的,虽然保证count独占了,但是不能保证此时还是满足count==items.length这个条件,打个比方:
首先生产者A线程发现队列已满,然后进入notFull的等待集,这时候消费者B线程从队列中取出一个元素,然后唤醒nutFull等待集中的线程并且释放锁,此时所有线程又开始竞争锁,假设是生产者B线程获得锁,然后向队列中放入一个元素,最后释放锁,此时所有线程又开始竞争锁,终于生产者线程A获得锁,从await方法返回,这时候它必须重新测试下条件是否满足,不然按照我说的流程就会出现问题;
4 楼 337240552 2012-07-25  
总结的不错 不过如果是初学者建议看下java编程思想21章 并发 讲的很详细。
3 楼 DiaoCow 2012-07-25  
railway 写道
总结得还行,不过Java锁并不只这些。
另外,你的notFull、notEmpty变量名我觉得取名full、empty更适合吧。


1.是的,java锁还有其他东西,昨天只温习了这些,所以就先总结了下,其他一定慢慢补上;
2.那段生产者消费者代码,我是摘录java sdk中的代码,一开始我的想法和你一样觉得名字有些别扭,但是后来这么一想,似乎也说的通:当一个生产者需要放入队列时,发现队列已满,这时候它会进入notFull的等待集中,当他收到notFull(队列不满的信号时),它又可以出来活动了; 这只是我说服自己的想法,呵呵
2 楼 railway 2012-07-25  
总结得还行,不过Java锁并不只这些。
另外,你的notFull、notEmpty变量名我觉得取名full、empty更适合吧。
1 楼 tenderuser 2012-07-25  
 while (count == items.length)  // 一定要是while循环  
         notFull.await();  

这个地方为什么一定要用while循环呢? 为什么不直接使用if判断? 在这之前已经获得锁了,已经可以保证对count的独占了(这里只有put和take方法)。。

相关推荐

    Java基础知识点总结.docx

    无论是工作学习,不断的总结是必不可少的。只有不断的总结,发现问题,弥补...Java锁小结 321 java.util.concurrent.locks包下常用的类 326 NIO(New IO) 327 volatile详解 337 Java 8新特性 347 Java 性能优化 362

    java多线程编程总结

    详细的讲述了多线程的各种用法 Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 ...Java线程:大总结

    java 锁的类型介绍总结

    java 锁的类型介绍

    Java多线程编程总结

    Java 线程系列博文总结word化,编目如下,欢迎互相学习交流: Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:...

    Java锁的知识总结及实例代码共7页.pdf.zip

    Java锁的知识总结及实例代码共7页.pdf.zip

    Java并发编程技术总结

    Java并发编程技术总结,所含内容有并发特性、并发锁、线程池、并发场景解决方案等,对于性能思考和内容参考资料有一定说明

    MySQL与Java锁的学习

    MySQL与Java锁的学习,总结笔记

    Java面试资料总结

    此Java面试资料总结囊括JVM垃圾回收,JVM内存模型以及java基础知识笔试和java面试宝典,更有SpringMVC经典面试题,MyBatis相关知识,剑指offer名企面试笔试算法题,MYSQL性能优化以及索引和锁相关知识。

    Java 线程总结

    Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 ...Java线程:大总结

    java 面试题 总结

    JAVA相关基础知识 1、面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用...

    Java后端面试问题整理.docx

    • 熟悉Java多线程并发中线程基本方法,线程池,线程生命周期,熟悉Java锁中常见锁分类(乐观/悲观锁、自旋锁、独/共享锁、可重入锁、公平/非公平锁、分段锁、偏向锁,轻/重量级锁)和基本的锁升级策略

    Java面试宝典2021-多线程,锁,同步.pdf

    最新java面试关于多线程,锁,同步相关知识总结

    Java多线程之显示锁和内置锁总结详解

    主要介绍了Java多线程之显示锁和内置锁总结详解,具有一定参考价值,需要的朋友可以了解下。

    Java 锁的知识总结及实例代码

    主要介绍了Java 锁的知识总结及实例代码,需要的朋友可以参考下

    各大公司Java后端开发面试题总结.pdf

    内容概要:涵盖各大公司Java后端开发面试的常见考点,例如:Java内存模型、java GC、Synchronized 与Lock锁、java集合、线程池、Spring的IOC等等。帮助你系统复习并掌握核心知识。 适用人群:Java后端开发工程师、...

    java 多线程设计模式 进程详解

    第八章 和同步相关的高级主题 同步术语 预防死锁 锁饥饿 非线程安全的类 总结 第九章 多处理器机器上的并行化 单线程程序并行化 内层循环线程化 循环输出 多处理器扩展 总结 第十章 线程组 线程组概念 创建线程...

    Java高频核心面试总结完整版

    Java高频核心面试总结完整版,包括锁,多线程等核心点

Global site tag (gtag.js) - Google Analytics