JDK同步控制工具,JAVA高并发程序设计
来源:互联网 发布:mac number 编辑:程序博客网 时间:2024/06/06 14:07
同步控制是并发程序的重要手段之一,我们平常用过最多的Synchronized就是其中一种简单的方法,此外还有Object.wait(),Object.notify()等方法。在JDK之中,还有其他好用的工具。
重入锁_ReentrantLock:
一个可重入的互斥锁Lock,它具有与使用synchronized方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。ReentrantLock将由最近成功获得锁,并且还没有释放该锁的线程所拥有。当锁没有被另一个线程所拥有时,调用lock的线程将成功获取该锁并返回。如果当前线程已经拥有该锁,此方法将立即返回。可以使用isHeldByCurrentThread()和getHoldCount()方法来检查此情况是否发生。举个栗子:
public class Demo_1 implements Runnable{ public static ReentrantLock lock = new ReentrantLock(); public static int i = 0; @Override public void run() { for (int j = 0; j < 1000000; j++) { lock.lock(); try { i++; } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } } public static void main(String[] args) throws Exception { Demo_1 A = new Demo_1(); Thread t1 = new Thread(A); Thread t2 = new Thread(A); t1.start();t2.start(); t1.join();t2.join(); }}
使用重入锁,在并发时,保护i的安全性。重入锁还有一个特点,跟它的名字一样,可以反复进如入:
for (int j = 0; j < 1000000; j++) { lock.lock(); lock.lock(); try { i++; } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); lock.unlock(); } }
跟synchronized相比,重入锁有显示操作,必须手动指定何时加锁和释放锁,对逻辑控制的灵活性要好于synchronized,唯一注意的就是必须释放锁。另外,重入锁还可以提供中断功能。使用synchronized时,一个线程在等待锁,最后结果就两种,要么获得锁,要么一直等待下去,这种情况对于实际业务需求来讲,并不友好。比如你朝思暮想的女朋友来看你了,在这种干柴烈火,风花雪月,月黑风高的时候,你正准备干点什么,女朋友亲戚来了,这时候你难道要一直等下去吗,那肯定不行,当然是停下来,然后开始学习
public class Demo_2 implements Runnable { public static ReentrantLock rLockA = new ReentrantLock(); public static ReentrantLock rLockB = new ReentrantLock(); int lock; public Demo_2(int lock) { this.lock = lock; } @Override public void run() { try { if (lock == 1) { rLockA.lockInterruptibly(); System.out.println("占用lock="+lock+":"+System.currentTimeMillis()); try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } rLockB.lockInterruptibly(); } else { System.out.println("占用lock="+lock+":"+System.currentTimeMillis()); rLockB.lockInterruptibly(); try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } rLockA.lockInterruptibly(); } } catch (Exception e) { // TODO: handle exception } finally { if (rLockA.isHeldByCurrentThread()) rLockA.unlock(); if (rLockB.isHeldByCurrentThread()) rLockB.unlock(); System.out.println(Thread.currentThread().getId() + " :线程退出 \b lock="+lock); } } public static void main(String[] args) throws Exception { Demo_2 demoA = new Demo_2(1); Demo_2 demoB = new Demo_2(2); Thread rA = new Thread(demoA); Thread rB = new Thread(demoB); rA.start();rB.start(); Thread.sleep(1000); rB.interrupt(); }}
当rA和rB同时执行,rA先占用lockA,再占用lockB,而rB先占用lock2,再占用lockA,这样就形成了相互等待。在这里,我们使用了 lockInterruptibly() 这个方法,这是一个可以对中断,休眠的线程进行响应的锁申请操作。
在上面的列子中,lockInterruptibly() 的优先作用是响应中断,就好比有个特工深入敌后,随时执行外面给的命令,因为外面的人进不来。最后我们调用了interrupt 方法,来中断rB线程,那么rB就会放弃lockA锁的申请,同时释放lockB的锁,这样rA就可以继续执行下去了。
除了这种等待外部通知外,还提供了一种其他方法:限时等待。顾名思义,就是在指定时间内,线程会一直等待锁的获取,超出时间就不再等待了。这里我们用 tryLock() 来实现:
public class Demo_3 implements Runnable { public static ReentrantLock rLock = new ReentrantLock(); public Demo_3() { System.out.println("初始化:"+Thread.currentThread().getId()); } @Override public void run() { try { if (rLock.tryLock(5, TimeUnit.SECONDS)) { Thread.sleep(6000); System.out.println("执行完成:"+Thread.currentThread().getId()); } else { System.out.println("获取锁失败"); } } catch (Exception e) { e.printStackTrace(); } finally { if (rLock.isHeldByCurrentThread()) { rLock.unlock(); } } } public static void main(String[] args) { Demo_3 demo = new Demo_3(); Thread t1 = new Thread(demo); Thread t2 = new Thread(demo); t1.start(); t2.start(); }}
tryLock() 的两个参数也很好理解,一个是等待时长,另一个就是时间单位。如果不带参数,就表示不等待,如果当前锁没有被其他线程占用,就直接返回true,反之直接返回false。
Condition 条件:
使用Synchronized的时候,我们可以用wait()和notify()方法来达到控制线程的目的。同样的在重入锁中,也有类似的方法,await(),awaitUninterruptibly()和singal()。
- await():当前线程等待,同时释放锁,其他线程使用singal()或者singalAll()方法时,重新获得锁并继续执行。当线程中断时,能跳出等待。
- awaitUninterruptibly():和await()功能差不多,但是它无法等待过程中响应中断。
- singal():唤醒另一个在等待中的线程。
阅读全文
0 0
- JDK同步控制工具,JAVA高并发程序设计
- java高并发程序设计总结五:jdk并发包其他同步控制工具类:ReadWriteLock/CountDownLatch/CyclicBarrier/LockSupport
- 《Java高并发程序设计》学习 --3.1多线程的团队协作:同步控制
- Java高并发程序设计 JDK并发包(上)
- 《Java高并发程序设计》总结--3. JDK并发包
- 《Java高并发程序设计》学习 --3.3 JDK的并发容器
- 实战Java高并发程序设计(三)JDK并发包
- Java高并发编程:同步工具类
- java高并发程序设计
- java高并发程序设计
- java高并发程序设计
- Java高并发程序设计
- JAVA高并发程序设计
- Java高并发程序设计
- java高并发程序设计学习笔记五六JDK并发包
- java高并发程序设计总结三:JDK并发包之ReentrantLock重入锁
- java高并发程序设计总结四:JDK并发包之信号量Semaphore
- Java高并发程序设计入门
- Luncene学习笔记 -- day03 入门程序
- 在springboot项目中引入swagger2时出现Circular view path [swagger-ui]
- Android手机系统数据连接核心类-java层说明
- Is it possible to implement IPv6 on a virtual interface (eth0:1 interface) in Linux?
- win7系统开机出现OEM7GRUB 0.4.4提示无法进入系统的原因及两种解决方法
- JDK同步控制工具,JAVA高并发程序设计
- 智力题--涂色练习
- Unity3d之动态连接Mesh Renderer和Collider
- Web Analytics 杂谈(下)
- [bigdata-089]go 以http get从server端读取json然后转化成json格式打印输出
- Recyclerview不显示内容
- X-Forwarded-For绕过服务器IP地址过滤
- Context 家族史!
- VC调用Matlab生成的dll