JDK并发包之同步控制

一、重入锁

重入锁使用java.util.concurrent.locks.ReentrantLock来实现。示例代码如下:

public class TryReentrantLock implements Runnable{static ReentrantLock lock=new ReentrantLock();static int i=0;@Overridepublic void run() {for(int j=0;j<10000;j++){lock.lock();try{i++;}finally {lock.unlock();}//重入锁可以反复进入,当然这种进入仅限于一个线程!因此可以如下:/*lock.lock(); lock.lock();try{i++;}finally {lock.unlock();lock.unlock();}*/}}public static void main(String[] args) throws InterruptedException {TryReentrantLock l=new TryReentrantLock();Thread t1=new Thread(l);Thread t2=new Thread(l);t1.start(); t2.start();t1.join(); t2.join();System.out.println(i);}
}

对于synchronized来说,如果一个线程在等待锁,那么结果只有两种情况,要么它获得这把锁继续执行,要么继续等待锁。而对于使用重入锁的线程来说则不同,线程在等待锁的过程中,程序可以根据需要取消对锁的请求。

public class IntLock implements Runnable{public static ReentrantLock lock1=new ReentrantLock();public static ReentrantLock lock2=new ReentrantLock();int state;/*控制加锁顺序,便于产生死锁。*/public IntLock(int state){this.state=state;}@Overridepublic void run() {try{if(state==1){lock1.lockInterruptibly(); //设置可中断的锁try{Thread.sleep(500); //便于产生死锁}catch (InterruptedException e){e.printStackTrace();}lock2.lockInterruptibly();}else{lock2.lockInterruptibly();try{Thread.sleep(500);}catch (InterruptedException e){e.printStackTrace();}lock1.lockInterruptibly();}}catch (Exception e){e.printStackTrace();}finally {if(lock1.isHeldByCurrentThread()) lock1.unlock();if(lock2.isHeldByCurrentThread()) lock2.unlock();System.out.println(Thread.currentThread().getName()+" :quit!");}}public static void main(String[] args) throws InterruptedException {IntLock intLock1=new IntLock(1);IntLock intLock2=new IntLock(2);Thread t1=new Thread(intLock1);t1.setName("t1");Thread t2=new Thread(intLock2);t2.setName("t2");t1.start(); t2.start();Thread.sleep(1000);t2.interrupt();}
}

使用tryLock()进行限时等待。

public class TimeLock implements Runnable{public static ReentrantLock lock=new ReentrantLock();@Overridepublic void run() {try{if(lock.tryLock(5, TimeUnit.SECONDS)){//注意返回布尔值.如果使用无参数的tryLock方法,// 当锁被占用时,线程会不等待,并返回false。Thread.sleep(6000);}else{System.out.println("Get lock failed!");}}catch (Exception e){e.printStackTrace();}finally {if (lock.isHeldByCurrentThread()) lock.unlock();}}public static void main(String[] args){TimeLock timeLock=new TimeLock();Thread t1=new Thread(timeLock);Thread t2=new Thread(timeLock);t1.start();t2.start();}
}

公平锁:

大多数情况下,锁的申请都是不公平,随机的。而公平锁,讲究“先来后到”!因此公平锁的一大特点是不会产生饥饿。重入锁允许我们对其公平性进行设置:

public ReentrantLock(boolean fair); //true表示公平锁

公平锁缺点:性能相对低下。

二、重入锁的好基友Condition

Condition的做用类似于wait()和notify()只不过Condition和ReentrantLock配合。

Condition接口的基本方法:

void await() throws InterruptedException //释放当前线程持有的锁,进入等待状态,当其他线程使用signal或signalAll()方法时继续执行。当线程被中断时会跳出等待。void awaitUninterruptibly();与await()方法相似,当中断时不会跳出等待。void signal();
void signalAll();

用法示例:

public class ReentrantCondition implements Runnable{static ReentrantLock lock=new ReentrantLock();static Condition condition=lock.newCondition();@Overridepublic void run() {try{lock.lock();System.out.println(Thread.currentThread().getName()+" is running fast!");condition.await();System.out.println(Thread.currentThread().getName()+" is going no.");}catch (InterruptedException e){e.printStackTrace();}finally {lock.unlock();}}public static void main(String[] args) throws InterruptedException {ReentrantCondition rc=new ReentrantCondition();Thread t=new Thread(rc,"King of Lock");t.start();Thread.sleep(2000);lock.lock(); //调用signal前先要获得锁
        condition.signal();lock.unlock(); //调用singal后要释放锁,以让给被唤醒的线程。
    }
}

三、允许多个线程同时访问:信号量(Semaphore)

Semaphore可以指定多个线程同时访问一个资源。

public Semaphore(int permits); //permits指定同时能有几个线程访问同一资源。
public Semaphore(int permits,boolean fair) //fair指定是否采用公平锁

Semaphore主要的逻辑方法有:

public void acquire()  //尝试获得一个准入许可,若无法获得,则线程会等待,直到有线程释放了一个许可,或者当前线程被中断
public void acquireUninterruptibly() //不响应中断
public void release() //释放一个许可

四、ReadWriteLock读写锁

读写锁允许多个线程同时读。

五、CountDownLatch倒计时器

通常用来控制线程等待,可以让某个线程等待直到倒计时结束,再开始执行。

public CountDownLatch(int count) //count为需要完成几个线程上的任务,CountDownLatch上的线程才能继续执行。

示例代码:

public class CountDownLatchDemo implements Runnable{static final CountDownLatch latch=new CountDownLatch(10); //需要完成10个线程的任务,// CountDownLatch上的线程才能继续执行static final CountDownLatchDemo demo=new CountDownLatchDemo();@Overridepublic void run() {try{Thread.sleep(1000);System.out.println(Thread.currentThread().getName()+" :mission completed!");latch.countDown();//通知CountDownLatch一个任务已经完成。}catch (Exception e){e.printStackTrace();}}public static void main(String[] args) throws InterruptedException {ExecutorService ex= Executors.newFixedThreadPool(10);for(int i=0;i<10;i++){ex.submit(demo);}latch.await(); //设置要等待其他线程完成的那个线程System.out.println("Killed them all!");ex.shutdown();}
}

六、循环栅栏:CyclicBarrier

与CountDownLatch类似CyclicBarrier也是用来阻止线程继续执行,让线程进入等待状态。但此计数器可以反复使用。

public CyclicBarrier(int parties,Runnable barrierAction) //barrierAction为计数完成后要执行的动作

示例代码:

public class CyclicBarrierDemo {public static class Soldier implements Runnable{private String name;private final CyclicBarrier barrier;Soldier(String name,CyclicBarrier barrier){this.name=name;this.barrier=barrier;}@Overridepublic void run() {try{barrier.await(); //进入等待状态,直到所有线程完成计数。doWork();        //所有线程完成一次await,继续执行。barrier.await(); //第二次await再次进入等待状态。}catch (Exception e){}}void doWork(){try{Thread.sleep(Math.abs(new Random().nextInt()%10000));}catch (Exception e){e.printStackTrace();}System.out.println("任务完成!");}}public static class FlyRun implements Runnable{boolean flag;int count;public FlyRun(boolean flag,int count){this.flag=flag;this.count=count;}@Overridepublic void run() {if (flag) System.out.println("队长:"+count+" 个士兵完成任务!");else {System.out.println("队长:"+count+" 个士兵集合完毕!");flag=true;}}}public static void main(String[] args){final int count=12;Thread[] soldiers=new Thread[count];boolean flag=false;CyclicBarrier barrier=new CyclicBarrier(count,new FlyRun(flag,count));//集合队伍System.out.println("集合队伍!");for(int j=0;j<count;j++){System.out.println("士兵"+j+"报道!");soldiers[j]=new Thread(new Soldier("士兵"+j,barrier));soldiers[j].start();}}
}

七、线程阻塞工具类:LockSupport

LockSupport可以在线程内任意位置让线程阻塞。但与Object.wait()不同,它不需要先获得某个对象的锁,也不会抛出InterruptedException异常。示例代码:

public class LockSupportDemo {public static Object instance=new Object();public static ChangThread t1=new ChangThread("t1");public static ChangThread t2=new ChangThread("t2");public static class ChangThread extends Thread{public ChangThread(String name){super.setName(name);}@Overridepublic void run(){synchronized(instance){System.out.println("in"+getName());LockSupport.park();}}}public static void main(String[] args) throws InterruptedException {t1.start();Thread.sleep(100);t2.start();LockSupport.unpark(t1); //即使unpark()发生在park前,程序也能正常执行。
        LockSupport.unpark(t2);t1.join();t2.join();}
}

park还支持中断影响,且不抛出异常。

转载于:https://www.cnblogs.com/Shadowplay/p/7459166.html

Java并发程序设计(四)JDK并发包之同步控制相关推荐

  1. java 同步包_Java并发程序设计(四)JDK并发包之同步控制

    JDK并发包之同步控制 一.重入锁 重入锁使用java.util.concurrent.locks.ReentrantLock来实现.示例代码如下: public class TryReentrant ...

  2. Java并发的四种风味:Thread、Executor、ForkJoin和Actor

    原文地址:Java并发的四种风味:Thread.Executor.ForkJoin和Actor 这篇文章讨论了Java应用中并行处理的多种方法.从自己管理Java线程,到各种更好的几种解决方法,Exe ...

  3. Java 并发编程(四):如何保证对象的线程安全性

    本篇来谈谈 Java 并发编程:如何保证对象的线程安全性. 01.前言 先让我吐一句肺腑之言吧,不说出来会憋出内伤的.<Java 并发编程实战>这本书太特么枯燥了,尽管它被奉为并发编程当中 ...

  4. Java高并发程序设计学习笔记(五):JDK并发包(各种同步控制工具的使用、并发容器及典型源码分析(Hashmap等))...

    转自:https://blog.csdn.net/dataiyangu/article/details/86491786#2__696 1. 各种同步控制工具的使用 1.1. ReentrantLoc ...

  5. 【Java并发编程 四】Java的进程与线程

    什么是进程?进程是程序的⼀次执⾏过程,是系统运⾏程序的基本单位,因此进程是动态的.系统运行和关闭⼀个程序即是⼀个进程从创建,运⾏到消亡的过程.在 Java 中,当我们启动 main 函数时其实就是启动 ...

  6. Java并发(四)——synchronized、volatile

    文章目录 synchronized.volatile 1 Java内存模型JMM 2 伪共享 3 指令重排 4 synchronized 5 volatile 6 synchronized和Lock ...

  7. Java并发程序设计(二)Java并行程序基础

    Java并行程序基础 一.线程的生命周期 其中blocked和waiting的区别: 作者:赵老师 链接:https://www.zhihu.com/question/27654579/answer/ ...

  8. Java并发程序设计(八)设计模式与并发之单例模式

    设计模式与并发之单例模式 简单的单例实现: public class Singleton {private Singleton(){System.out.println("Creating ...

  9. Java并发(四)BlockingQueue的使用

    wait()和notifyAll()方法以一种非常低级的方式解决了任务互操作的问题,即每次交互时都需要握手.在许多情况下,你可以瞄准更高的抽象级别,使用同步队列来解决任务协作的问题.同步队列在任何时刻 ...

最新文章

  1. AI实时特效,魔幻修图,Adobe Photoshop相机拯救PS菜鸟
  2. SharePoint2013 访问“/”应用程序中的服务器错误。解决方案:
  3. CompletableFuture框架
  4. 软件测试周记录之jmeter
  5. SAP中查询用户操作日志的事务码
  6. ORACLE ORA-00600 [17059][]错误的排除
  7. 实战build-react(二)-------引入Ant Design(增加)
  8. c语言教材课后习题答案,C语言课后习题答案(最终).doc
  9. qstring如何初始化_qstringlist 初始化
  10. 使用Stream流时报java.lang.IllegalStateException: stream has already been operated upon or closed错误
  11. 图像处理算法工程师必备技能总结
  12. Vue--Vuex--使用/教程/实例
  13. NB-loT中的Niubility技术
  14. 100个世界上鲜为人知的奇闻怪事小知识(转)
  15. 会员卡充值系统小程序开发制作功能介绍
  16. ubuntu20.04-cuda100-cudnn7.6.5-tensorflow-gpu2.0.0安装测试记录
  17. 微信小程序云开发-批量上传文件到云储存空间
  18. 【Wayland】Weston多屏显示
  19. C#中sizeof用法
  20. zoj 2954 Hanoi Tower(汉诺塔)

热门文章

  1. http://www.himigame.com/mac-cocoa-application/893.html
  2. delphi编程模拟发送QQ2008消息!
  3. 卷首寄语:我们的今天,明天--致所有战斗在一线的同行们
  4. 强制卸载域控制器命令
  5. thinkcmf安装模板需要点击右键打开新页面的解决办法
  6. JAVA设计模式-策略模式
  7. 剑指Offer——二叉树的镜像
  8. java:BufferedReader接受输入进来的2个数字,并将它们相加
  9. 修改了n次效率还是不可接受
  10. libgdx学习记录9——FreeType,ttf中文显示